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