]> git.sur5r.net Git - openldap/blob - libraries/libldap/vc.c
0e4dc07dbc258a991703cb0864652eaaa59c5bfa
[openldap] / libraries / libldap / vc.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2017 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* ACKNOWLEDGEMENTS:
16  * This program was originally developed by Kurt D. Zeilenga for inclusion in
17  * OpenLDAP Software.
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23 #include <ac/stdlib.h>
24 #include <ac/string.h>
25 #include <ac/time.h>
26
27 #include "ldap-int.h"
28
29 /*
30  * LDAP Verify Credentials operation
31  *
32  * The request is an extended request with OID 1.3.6.1.4.1.4203.666.6.5 with value of
33  * the BER encoding of:
34  *
35  * VCRequest ::= SEQUENCE {
36  *              cookie [0] OCTET STRING OPTIONAL,
37  *              name    LDAPDN,
38  *              authentication  AuthenticationChoice,
39  *          controls [2] Controls OPTIONAL
40  * }
41  *
42  * where LDAPDN, AuthenticationChoice, and Controls are as defined in RFC 4511.
43  *
44  * The response is an extended response with no OID and a value of the BER encoding of
45  *
46  * VCResponse ::= SEQUENCE {
47  *              resultCode ResultCode,
48  *              diagnosticMessage LDAPString,
49  *              cookie [0] OCTET STRING OPTIONAL,
50  *              serverSaslCreds [1] OCTET STRING OPTIONAL,
51  *          controls [2] Controls OPTIONAL
52  * }
53  *
54  * where ResultCode is the result code enumeration from RFC 4511, and LDAPString and Controls are as
55  * defined in RFC 4511.
56  */
57
58 int ldap_parse_verify_credentials(
59         LDAP *ld,
60         LDAPMessage *res,
61         int * code,
62         char ** diagmsg,
63     struct berval **cookie,
64         struct berval **screds,
65         LDAPControl ***ctrls)
66 {
67         int rc;
68         char *retoid = NULL;
69         struct berval *retdata = NULL;
70
71         assert(ld != NULL);
72         assert(LDAP_VALID(ld));
73         assert(res != NULL);
74         assert(code != NULL);
75         assert(diagmsg != NULL);
76
77         rc = ldap_parse_extended_result(ld, res, &retoid, &retdata, 0);
78
79         if( rc != LDAP_SUCCESS ) {
80                 ldap_perror(ld, "ldap_parse_verify_credentials");
81                 return rc;
82         }
83
84         if (retdata) {
85                 ber_tag_t tag;
86                 ber_len_t len;
87                 ber_int_t i;
88                 BerElement * ber = ber_init(retdata);
89                 struct berval diagmsg_bv = BER_BVNULL;
90                 if (!ber) {
91                     rc = ld->ld_errno = LDAP_NO_MEMORY;
92                         goto done;
93                 }
94
95                 rc = LDAP_DECODING_ERROR;
96
97                 if (ber_scanf(ber, "{im" /*"}"*/, &i, &diagmsg_bv) == LBER_ERROR) {
98                         goto ber_done;
99                 }
100                 if ( diagmsg != NULL ) {
101                         *diagmsg = LDAP_MALLOC( diagmsg_bv.bv_len + 1 );
102                         AC_MEMCPY( *diagmsg, diagmsg_bv.bv_val, diagmsg_bv.bv_len );
103                         (*diagmsg)[diagmsg_bv.bv_len] = '\0';
104                 }
105                 *code = i;
106
107                 tag = ber_peek_tag(ber, &len);
108                 if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE) {
109                         if (ber_scanf(ber, "O", cookie) == LBER_ERROR)
110                                 goto ber_done;
111                         tag = ber_peek_tag(ber, &len);
112                 }
113
114                 if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_SCREDS) {
115                         if (ber_scanf(ber, "O", screds) == LBER_ERROR)
116                                 goto ber_done;
117                         tag = ber_peek_tag(ber, &len);
118                 }
119
120                 if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS) {
121                     int nctrls = 0;
122                         char * opaque;
123
124                     *ctrls = LDAP_MALLOC(1 * sizeof(LDAPControl *));
125
126                         if (!*ctrls) {
127                                 rc = LDAP_NO_MEMORY;
128                                 goto ber_done;
129                         }
130
131                         *ctrls[nctrls] = NULL;
132
133                         for(tag = ber_first_element(ber, &len, &opaque);
134                                 tag != LBER_ERROR;
135                                 tag = ber_next_element(ber, &len, opaque))
136                     {
137                                 LDAPControl *tctrl;
138                                 LDAPControl **tctrls;
139
140                                 tctrl = LDAP_CALLOC(1, sizeof(LDAPControl));
141
142                                 /* allocate pointer space for current controls (nctrls)
143                                  * + this control + extra NULL
144                                  */
145                                 tctrls = !tctrl ? NULL : LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
146
147                                 if (!tctrls) {
148                                         /* allocation failure */
149                                         if (tctrl) LDAP_FREE(tctrl);
150                                         ldap_controls_free(*ctrls);
151                                         *ctrls = NULL;
152                                     rc = LDAP_NO_MEMORY;
153                                     goto ber_done;
154                                 }
155
156                                 tctrls[nctrls++] = tctrl;
157                                 tctrls[nctrls] = NULL;
158
159                                 tag = ber_scanf(ber, "{a" /*"}"*/, &tctrl->ldctl_oid);
160                                 if (tag == LBER_ERROR) {
161                                         *ctrls = NULL;
162                                         ldap_controls_free(tctrls);
163                                         goto ber_done;
164                                 }
165
166                                 tag = ber_peek_tag(ber, &len);
167                                 if (tag == LBER_BOOLEAN) {
168                                         ber_int_t crit;
169                                         tag = ber_scanf(ber, "b", &crit);
170                                         tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
171                                     tag = ber_peek_tag(ber, &len);
172                                 }
173
174                             if (tag == LBER_OCTETSTRING) {
175                     tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
176                 } else {
177                     BER_BVZERO( &tctrl->ldctl_value );
178                 }
179
180                 *ctrls = tctrls;
181                         }
182             }
183
184                 rc = LDAP_SUCCESS;
185
186         ber_done:
187             ber_free(ber, 1);
188     }
189
190 done:
191         ber_bvfree(retdata);
192         ber_memfree(retoid);
193         return rc;
194 }
195
196 int
197 ldap_verify_credentials(LDAP *ld,
198         struct berval   *cookie,
199         LDAP_CONST char *dn,
200         LDAP_CONST char *mechanism,
201         struct berval   *cred,
202     LDAPControl         **vcctrls,
203         LDAPControl             **sctrls,
204         LDAPControl             **cctrls,
205         int                             *msgidp)
206 {
207         int rc;
208         BerElement *ber;
209         struct berval reqdata;
210
211         assert(ld != NULL);
212         assert(LDAP_VALID(ld));
213         assert(msgidp != NULL);
214
215         ber = ber_alloc_t(LBER_USE_DER);
216         if (dn == NULL) dn = "";
217
218         if (mechanism == LDAP_SASL_SIMPLE) {
219                 assert(!cookie);
220
221                 rc = ber_printf(ber, "{stO" /*"}"*/,
222                         dn, LDAP_AUTH_SIMPLE, cred);
223
224         } else {
225                 if (!cred || BER_BVISNULL(cred)) {
226                         if (cookie) {
227                                 rc = ber_printf(ber, "{tOst{sN}" /*"}"*/,
228                                         LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, cookie,
229                                         dn, LDAP_AUTH_SASL, mechanism);
230                         } else {
231                                 rc = ber_printf(ber, "{st{sN}N" /*"}"*/,
232                                         dn, LDAP_AUTH_SASL, mechanism);
233                         }
234                 } else {
235                         if (cookie) {
236                                 rc = ber_printf(ber, "{tOst{sON}" /*"}"*/,
237                                         LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, cookie,
238                                         dn, LDAP_AUTH_SASL, mechanism, cred);
239                         } else {
240                                 rc = ber_printf(ber, "{st{sON}" /*"}"*/,
241                                         dn, LDAP_AUTH_SASL, mechanism, cred);
242                         }
243                 }
244         }
245
246         if (rc < 0) {
247                 rc = ld->ld_errno = LDAP_ENCODING_ERROR;
248                 goto done;
249         }
250
251         if (vcctrls && *vcctrls) {
252                 LDAPControl *const *c;
253
254                 rc = ber_printf(ber, "t{" /*"}"*/, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS);
255
256                 for (c=vcctrls; *c; c++) {
257                         rc = ldap_pvt_put_control(*c, ber);
258                         if (rc != LDAP_SUCCESS) {
259                                 rc = ld->ld_errno = LDAP_ENCODING_ERROR;
260                                 goto done;
261                         }
262                 }
263
264                 rc = ber_printf(ber, /*"{{"*/ "}N}");
265
266         } else {
267                 rc = ber_printf(ber, /*"{"*/ "N}");
268         }
269
270         if (rc < 0) {
271                 rc = ld->ld_errno = LDAP_ENCODING_ERROR;
272                 goto done;
273         }
274
275
276         rc = ber_flatten2(ber, &reqdata, 0);
277         if (rc < 0) {
278                 rc = ld->ld_errno = LDAP_ENCODING_ERROR;
279                 goto done;
280         }
281
282         rc = ldap_extended_operation(ld, LDAP_EXOP_VERIFY_CREDENTIALS,
283                 &reqdata, sctrls, cctrls, msgidp);
284
285 done:
286         ber_free(ber, 1);
287         return rc;
288 }
289
290 int
291 ldap_verify_credentials_s(
292         LDAP *ld,
293         struct berval   *cookie,
294         LDAP_CONST char *dn,
295         LDAP_CONST char *mechanism,
296         struct berval   *cred,
297     LDAPControl         **vcictrls,
298         LDAPControl             **sctrls,
299         LDAPControl             **cctrls,
300         int                             *rcode,
301         char                    **diagmsg,
302         struct berval   **scookie,
303         struct berval   **scred,
304     LDAPControl         ***vcoctrls)
305 {
306         int                             rc;
307         int                             msgid;
308         LDAPMessage             *res;
309
310         rc = ldap_verify_credentials(ld, cookie, dn, mechanism, cred, vcictrls, sctrls, cctrls, &msgid);
311         if (rc != LDAP_SUCCESS) return rc;
312
313         if (ldap_result(ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res) == -1 || !res) {
314                 return ld->ld_errno;
315         }
316
317         rc = ldap_parse_verify_credentials(ld, res, rcode, diagmsg, scookie, scred, vcoctrls);
318         if (rc != LDAP_SUCCESS) {
319                 ldap_msgfree(res);
320                 return rc;
321         }
322
323         return( ldap_result2error(ld, res, 1));
324 }
325
326 #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE
327 int
328 ldap_verify_credentials_interactive (
329         LDAP *ld,
330         LDAP_CONST char *dn, /* usually NULL */
331         LDAP_CONST char *mech,
332         LDAPControl **vcControls,
333         LDAPControl **serverControls,
334         LDAPControl **clientControls,
335
336         /* should be client controls */
337         unsigned flags,
338         LDAP_SASL_INTERACT_PROC *proc,
339         void *defaults,
340     void *context;
341         
342         /* as obtained from ldap_result() */
343         LDAPMessage *result,
344
345         /* returned during bind processing */
346         const char **rmech,
347         int *msgid )
348 {
349         if (!ld && context) {
350                 assert(!dn);
351                 assert(!mech);
352                 assert(!vcControls);
353                 assert(!serverControls);
354                 assert(!defaults);
355                 assert(!result);
356                 assert(!rmech);
357                 assert(!msgid);
358
359                 /* special case to avoid having to expose a separate dispose context API */
360                 sasl_dispose((sasl_conn_t)context);
361         return LDAP_SUCCESS;
362     }
363
364     ld->ld_errno = LDAP_NOT_SUPPORTED;
365     return ld->ld_errno;
366 }
367 #endif