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 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 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 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 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