]> git.sur5r.net Git - openldap/blob - libraries/libldap/vc.c
Extend Verify Credentials encode/decode per -devel post.
[openldap] / libraries / libldap / vc.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2010 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 orignally 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 [3] 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  *              authzid [2] OCTET STRING OPTIONAL
52  *          controls [3] Controls OPTIONAL
53  * }
54  *
55  * where ResultCode is the result code enumeration from RFC 4511, and LDAPString and Controls are as
56  * defined in RFC 4511.
57  */
58
59 int ldap_parse_verify_credentials(
60         LDAP *ld,
61         LDAPMessage *res,
62         int * code,
63         char ** diagmsg,
64     struct berval **cookie,
65         struct berval **screds,
66         struct berval **authzid,
67         LDAPControl ***ctrls)
68 {
69         int rc;
70         char *retoid = NULL;
71         struct berval *retdata = NULL;
72
73         assert(ld != NULL);
74         assert(LDAP_VALID(ld));
75         assert(res != NULL);
76         assert(authzid != NULL);
77
78         *authzid = NULL;
79
80         rc = ldap_parse_extended_result(ld, res, &retoid, &retdata, 0);
81
82         if( rc != LDAP_SUCCESS ) {
83                 ldap_perror(ld, "ldap_parse_verify_credentials");
84                 return rc;
85         }
86
87     if (retdata) {
88             ber_tag_t tag;
89                 ber_len_t len;
90                 ber_int_t i;
91             BerElement * ber = ber_init(retdata);
92                 if (!ber) {
93                     rc = ld->ld_errno = LDAP_NO_MEMORY;
94                         goto done;
95                 }
96
97                 ber_scanf(ber, "{is" /*"}"*/, &i, diagmsg);
98                 *code = i;
99
100                 tag = ber_peek_tag(ber, &len);
101                 if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE) {
102                         ber_scanf(ber, "O", cookie);
103                     tag = ber_peek_tag(ber, &len);
104                 }
105
106                 if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_SCREDS) {
107                         ber_scanf(ber, "O", screds);
108                     tag = ber_peek_tag(ber, &len);
109                 }
110
111                 if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_AUTHZID) {
112                         ber_scanf(ber, "O", authzid);
113                 }
114
115                 if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS) {
116                     int nctrls = 0;
117                         char * opaque;
118
119                     *ctrls = LDAP_MALLOC(1 * sizeof(LDAPControl *));
120
121                         if (*ctrls) {
122                                 rc = LDAP_NO_MEMORY;
123                                 goto done;
124                         }
125
126                         *ctrls[nctrls] = NULL;
127
128                         for(tag = ber_first_element(ber, &len, &opaque);
129                                 tag != LBER_ERROR;
130                                 tag = ber_next_element(ber, &len, opaque))
131                     {
132                                 LDAPControl *tctrl;
133                                 LDAPControl **tctrls;
134
135                                 tctrl = LDAP_CALLOC(1, sizeof(LDAPControl));
136
137                                 /* allocate pointer space for current controls (nctrls)
138                                  * + this control + extra NULL
139                                  */
140                                 tctrls = !tctrl ? NULL : LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
141
142                                 if (!tctrls) {
143                                         /* allocation failure */
144                                         if (tctrl) LDAP_FREE(tctrl);
145                                         ldap_controls_free(*ctrls);
146                                         *ctrls = NULL;
147                                     rc = LDAP_NO_MEMORY;
148                                     goto done;
149                                 }
150
151                                 tctrls[nctrls++] = tctrl;
152                                 tctrls[nctrls] = NULL;
153
154                                 tag = ber_scanf(ber, "{a" /*"}"*/, &tctrl->ldctl_oid);
155                                 if (tag == LBER_ERROR) {
156                                         *ctrls = NULL;
157                                         ldap_controls_free(tctrls);
158                                         rc = LDAP_DECODING_ERROR;
159                                         goto done;
160                                 }
161
162                                 tag = ber_peek_tag(ber, &len);
163                                 if (tag == LBER_BOOLEAN) {
164                                         ber_int_t crit;
165                                         tag = ber_scanf(ber, "b", &crit);
166                                         tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
167                                     tag = ber_peek_tag(ber, &len);
168                                 }
169
170                             if (tag == LBER_OCTETSTRING) {
171                     tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
172                 } else {
173                     BER_BVZERO( &tctrl->ldctl_value );
174                 }
175
176                 *ctrls = tctrls;
177                         }
178             }
179
180             ber_free(ber, 1);
181     }
182
183 done:
184         ber_bvfree(retdata);
185         ber_memfree(retoid);
186         return rc;
187 }
188
189 int
190 ldap_verify_credentials(LDAP *ld,
191         struct berval   *cookie,
192         LDAP_CONST char *dn,
193         LDAP_CONST char *mechanism,
194         struct berval   *cred,
195     LDAPControl         **vcctrls,
196         LDAPControl             **sctrls,
197         LDAPControl             **cctrls,
198         int                             *msgidp)
199 {
200         int rc;
201         BerElement *ber;
202         struct berval * reqdata;
203
204         assert(ld != NULL);
205         assert(LDAP_VALID(ld));
206         assert(msgidp != NULL);
207
208         ber = ber_alloc_t(LBER_USE_DER);
209         if (dn == NULL) dn = "";
210
211         if (mechanism == LDAP_SASL_SIMPLE) {
212                 assert(!cookie);
213
214                 rc = ber_printf(ber, "{stO" /*"}"*/,
215                         dn, LDAP_AUTH_SIMPLE, cred);
216
217         } else {
218                 if (!cred || BER_BVISNULL(cred)) {
219                         if (cookie) {
220                                 rc = ber_printf(ber, "{tOst{sN}" /*"}"*/,
221                                         LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, cookie,
222                                         dn, LDAP_AUTH_SASL, mechanism);
223                         } else {
224                                 rc = ber_printf(ber, "{st{sN}N" /*"}"*/,
225                                         dn, LDAP_AUTH_SASL, mechanism);
226                         }
227                 } else {
228                         if (cookie) {
229                                 rc = ber_printf(ber, "{tOst{sON}" /*"}"*/,
230                                         LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, cookie,
231                                         dn, LDAP_AUTH_SASL, mechanism, cred);
232                         } else {
233                                 rc = ber_printf(ber, "{st{sON}" /*"}"*/,
234                                         dn, LDAP_AUTH_SASL, mechanism, cred);
235                         }
236                 }
237         }
238
239     if (rc) goto done;
240
241     if (!rc && vcctrls && *vcctrls) {
242                 LDAPControl *const *c;
243
244                 rc = ber_printf(ber, "t{" /*"}"*/, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS);
245
246             for (c=vcctrls; *c; c++) {
247                         rc = ldap_pvt_put_control(*c, ber);
248                         if (rc != LDAP_SUCCESS) {
249                             rc = -1;
250                                 goto done;
251                         }
252                 }
253
254                 rc = ber_printf(ber, /*"{{"*/ "}N}");
255
256     } else {
257                 rc = ber_printf(ber, /*"{"*/ "N}");
258         }
259
260     if (rc) goto done;
261
262
263         ber_flatten(ber, &reqdata);
264
265         rc = ldap_extended_operation(ld, LDAP_EXOP_VERIFY_CREDENTIALS,
266                 reqdata, sctrls, cctrls, msgidp);
267
268 done:
269         ber_free(ber, 1);
270         return rc;
271 }
272
273 int
274 ldap_verify_credentials_s(
275         LDAP *ld,
276         struct berval   *cookie,
277         LDAP_CONST char *dn,
278         LDAP_CONST char *mechanism,
279         struct berval   *cred,
280     LDAPControl         **vcictrls,
281         LDAPControl             **sctrls,
282         LDAPControl             **cctrls,
283         int                             *rcode,
284         char                    **diagmsg,
285         struct berval   **scookie,
286         struct berval   **scred,
287         struct berval   **authzid,
288     LDAPControl         ***vcoctrls)
289 {
290         int                             rc;
291         int                             msgid;
292         LDAPMessage             *res;
293
294         rc = ldap_verify_credentials(ld, cookie, dn, mechanism, cred, vcictrls, sctrls, cctrls, &msgid);
295         if (rc != LDAP_SUCCESS) return rc;
296
297         if (ldap_result(ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res) == -1 || !res) {
298                 return ld->ld_errno;
299         }
300
301         rc = ldap_parse_verify_credentials(ld, res, rcode, diagmsg, scookie, scred, authzid, vcoctrls);
302         if (rc != LDAP_SUCCESS) {
303                 ldap_msgfree(res);
304                 return rc;
305         }
306
307         return( ldap_result2error(ld, res, 1));
308 }