1 1.9 christos /* $NetBSD: passwd.c,v 1.10 2025/09/05 21:16:23 christos Exp $ */ 2 1.2 lukem 3 1.4 tron /* $OpenLDAP$ */ 4 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 1.1 lukem * 6 1.10 christos * Copyright 1998-2024 The OpenLDAP Foundation. 7 1.1 lukem * All rights reserved. 8 1.1 lukem * 9 1.1 lukem * Redistribution and use in source and binary forms, with or without 10 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP 11 1.1 lukem * Public License. 12 1.1 lukem * 13 1.1 lukem * A copy of this license is available in the file LICENSE in the 14 1.1 lukem * top-level directory of the distribution or, alternatively, at 15 1.1 lukem * <http://www.OpenLDAP.org/license.html>. 16 1.1 lukem */ 17 1.1 lukem 18 1.1 lukem /* 19 1.1 lukem * int lutil_passwd( 20 1.1 lukem * const struct berval *passwd, 21 1.1 lukem * const struct berval *cred, 22 1.1 lukem * const char **schemes ) 23 1.1 lukem * 24 1.1 lukem * Returns true if user supplied credentials (cred) matches 25 1.1 lukem * the stored password (passwd). 26 1.1 lukem * 27 1.1 lukem * Due to the use of the crypt(3) function 28 1.1 lukem * this routine is NOT thread-safe. 29 1.1 lukem */ 30 1.1 lukem 31 1.5 christos #include <sys/cdefs.h> 32 1.9 christos __RCSID("$NetBSD: passwd.c,v 1.10 2025/09/05 21:16:23 christos Exp $"); 33 1.5 christos 34 1.1 lukem #include "portable.h" 35 1.1 lukem 36 1.1 lukem #include <stdio.h> 37 1.1 lukem #include <ac/stdlib.h> 38 1.1 lukem #include <ac/string.h> 39 1.2 lukem #include <ac/time.h> 40 1.1 lukem #include <ac/unistd.h> 41 1.1 lukem #include <ac/param.h> 42 1.1 lukem 43 1.1 lukem #ifdef SLAPD_CRYPT 44 1.1 lukem # include <ac/crypt.h> 45 1.1 lukem 46 1.1 lukem # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) 47 1.1 lukem # ifdef HAVE_SHADOW_H 48 1.1 lukem # include <shadow.h> 49 1.1 lukem # endif 50 1.1 lukem # ifdef HAVE_PWD_H 51 1.1 lukem # include <pwd.h> 52 1.1 lukem # endif 53 1.1 lukem # ifdef HAVE_AIX_SECURITY 54 1.1 lukem # include <userpw.h> 55 1.1 lukem # endif 56 1.1 lukem # endif 57 1.1 lukem #endif 58 1.1 lukem 59 1.1 lukem #include <lber.h> 60 1.1 lukem 61 1.1 lukem #include "ldap_pvt.h" 62 1.1 lukem #include "lber_pvt.h" 63 1.1 lukem 64 1.1 lukem #include "lutil_md5.h" 65 1.1 lukem #include "lutil_sha1.h" 66 1.1 lukem #include "lutil.h" 67 1.1 lukem 68 1.1 lukem static const unsigned char crypt64[] = 69 1.1 lukem "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./"; 70 1.1 lukem 71 1.1 lukem #ifdef SLAPD_CRYPT 72 1.1 lukem static char *salt_format = NULL; 73 1.1 lukem static lutil_cryptfunc lutil_crypt; 74 1.1 lukem lutil_cryptfunc *lutil_cryptptr = lutil_crypt; 75 1.1 lukem #endif 76 1.1 lukem 77 1.1 lukem /* KLUDGE: 78 1.1 lukem * chk_fn is NULL iff name is {CLEARTEXT} 79 1.1 lukem * otherwise, things will break 80 1.1 lukem */ 81 1.1 lukem struct pw_scheme { 82 1.1 lukem struct berval name; 83 1.1 lukem LUTIL_PASSWD_CHK_FUNC *chk_fn; 84 1.1 lukem LUTIL_PASSWD_HASH_FUNC *hash_fn; 85 1.1 lukem }; 86 1.1 lukem 87 1.1 lukem struct pw_slist { 88 1.1 lukem struct pw_slist *next; 89 1.1 lukem struct pw_scheme s; 90 1.1 lukem }; 91 1.1 lukem 92 1.1 lukem /* password check routines */ 93 1.1 lukem 94 1.1 lukem #define SALT_SIZE 4 95 1.1 lukem 96 1.1 lukem static LUTIL_PASSWD_CHK_FUNC chk_md5; 97 1.1 lukem static LUTIL_PASSWD_CHK_FUNC chk_smd5; 98 1.1 lukem static LUTIL_PASSWD_HASH_FUNC hash_smd5; 99 1.1 lukem static LUTIL_PASSWD_HASH_FUNC hash_md5; 100 1.1 lukem 101 1.1 lukem 102 1.1 lukem #ifdef LUTIL_SHA1_BYTES 103 1.1 lukem static LUTIL_PASSWD_CHK_FUNC chk_ssha1; 104 1.1 lukem static LUTIL_PASSWD_CHK_FUNC chk_sha1; 105 1.1 lukem static LUTIL_PASSWD_HASH_FUNC hash_sha1; 106 1.1 lukem static LUTIL_PASSWD_HASH_FUNC hash_ssha1; 107 1.1 lukem #endif 108 1.1 lukem 109 1.1 lukem 110 1.1 lukem #ifdef SLAPD_CRYPT 111 1.1 lukem static LUTIL_PASSWD_CHK_FUNC chk_crypt; 112 1.1 lukem static LUTIL_PASSWD_HASH_FUNC hash_crypt; 113 1.1 lukem 114 1.1 lukem #if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) 115 1.1 lukem static LUTIL_PASSWD_CHK_FUNC chk_unix; 116 1.1 lukem #endif 117 1.1 lukem #endif 118 1.1 lukem 119 1.1 lukem /* password hash routines */ 120 1.1 lukem 121 1.1 lukem #ifdef SLAPD_CLEARTEXT 122 1.1 lukem static LUTIL_PASSWD_HASH_FUNC hash_clear; 123 1.1 lukem #endif 124 1.1 lukem 125 1.1 lukem static struct pw_slist *pw_schemes; 126 1.1 lukem static int pw_inited; 127 1.1 lukem 128 1.1 lukem static const struct pw_scheme pw_schemes_default[] = 129 1.1 lukem { 130 1.1 lukem #ifdef LUTIL_SHA1_BYTES 131 1.1 lukem { BER_BVC("{SSHA}"), chk_ssha1, hash_ssha1 }, 132 1.1 lukem { BER_BVC("{SHA}"), chk_sha1, hash_sha1 }, 133 1.1 lukem #endif 134 1.1 lukem 135 1.1 lukem { BER_BVC("{SMD5}"), chk_smd5, hash_smd5 }, 136 1.1 lukem { BER_BVC("{MD5}"), chk_md5, hash_md5 }, 137 1.1 lukem 138 1.1 lukem #ifdef SLAPD_CRYPT 139 1.1 lukem { BER_BVC("{CRYPT}"), chk_crypt, hash_crypt }, 140 1.1 lukem # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) 141 1.1 lukem { BER_BVC("{UNIX}"), chk_unix, NULL }, 142 1.1 lukem # endif 143 1.1 lukem #endif 144 1.1 lukem 145 1.1 lukem #ifdef SLAPD_CLEARTEXT 146 1.1 lukem /* pseudo scheme */ 147 1.1 lukem { BER_BVC("{CLEARTEXT}"), NULL, hash_clear }, 148 1.1 lukem #endif 149 1.1 lukem 150 1.1 lukem { BER_BVNULL, NULL, NULL } 151 1.1 lukem }; 152 1.1 lukem 153 1.1 lukem int lutil_passwd_add( 154 1.1 lukem struct berval *scheme, 155 1.1 lukem LUTIL_PASSWD_CHK_FUNC *chk, 156 1.1 lukem LUTIL_PASSWD_HASH_FUNC *hash ) 157 1.1 lukem { 158 1.1 lukem struct pw_slist *ptr; 159 1.1 lukem 160 1.1 lukem if (!pw_inited) lutil_passwd_init(); 161 1.1 lukem 162 1.1 lukem ptr = ber_memalloc( sizeof( struct pw_slist )); 163 1.1 lukem if (!ptr) return -1; 164 1.1 lukem ptr->next = pw_schemes; 165 1.1 lukem ptr->s.name = *scheme; 166 1.1 lukem ptr->s.chk_fn = chk; 167 1.1 lukem ptr->s.hash_fn = hash; 168 1.1 lukem pw_schemes = ptr; 169 1.1 lukem return 0; 170 1.1 lukem } 171 1.1 lukem 172 1.1 lukem void lutil_passwd_init() 173 1.1 lukem { 174 1.1 lukem struct pw_scheme *s; 175 1.1 lukem 176 1.1 lukem pw_inited = 1; 177 1.1 lukem 178 1.1 lukem for( s=(struct pw_scheme *)pw_schemes_default; s->name.bv_val; s++) { 179 1.1 lukem if ( lutil_passwd_add( &s->name, s->chk_fn, s->hash_fn ) ) break; 180 1.1 lukem } 181 1.1 lukem } 182 1.1 lukem 183 1.1 lukem void lutil_passwd_destroy() 184 1.1 lukem { 185 1.1 lukem struct pw_slist *ptr, *next; 186 1.1 lukem 187 1.1 lukem for( ptr=pw_schemes; ptr; ptr=next ) { 188 1.1 lukem next = ptr->next; 189 1.1 lukem ber_memfree( ptr ); 190 1.1 lukem } 191 1.1 lukem } 192 1.1 lukem 193 1.1 lukem static const struct pw_scheme *get_scheme( 194 1.1 lukem const char* scheme ) 195 1.1 lukem { 196 1.1 lukem struct pw_slist *pws; 197 1.1 lukem struct berval bv; 198 1.1 lukem 199 1.1 lukem if (!pw_inited) lutil_passwd_init(); 200 1.1 lukem 201 1.1 lukem bv.bv_val = strchr( scheme, '}' ); 202 1.1 lukem if ( !bv.bv_val ) 203 1.1 lukem return NULL; 204 1.1 lukem 205 1.1 lukem bv.bv_len = bv.bv_val - scheme + 1; 206 1.1 lukem bv.bv_val = (char *) scheme; 207 1.1 lukem 208 1.1 lukem for( pws=pw_schemes; pws; pws=pws->next ) { 209 1.1 lukem if ( ber_bvstrcasecmp(&bv, &pws->s.name ) == 0 ) { 210 1.1 lukem return &(pws->s); 211 1.1 lukem } 212 1.1 lukem } 213 1.1 lukem 214 1.1 lukem return NULL; 215 1.1 lukem } 216 1.1 lukem 217 1.1 lukem int lutil_passwd_scheme( 218 1.1 lukem const char* scheme ) 219 1.1 lukem { 220 1.1 lukem if( scheme == NULL ) { 221 1.1 lukem return 0; 222 1.1 lukem } 223 1.1 lukem 224 1.1 lukem return get_scheme(scheme) != NULL; 225 1.1 lukem } 226 1.1 lukem 227 1.1 lukem 228 1.1 lukem static int is_allowed_scheme( 229 1.1 lukem const char* scheme, 230 1.1 lukem const char** schemes ) 231 1.1 lukem { 232 1.1 lukem int i; 233 1.1 lukem 234 1.1 lukem if( schemes == NULL ) return 1; 235 1.1 lukem 236 1.1 lukem for( i=0; schemes[i] != NULL; i++ ) { 237 1.1 lukem if( strcasecmp( scheme, schemes[i] ) == 0 ) { 238 1.1 lukem return 1; 239 1.1 lukem } 240 1.1 lukem } 241 1.1 lukem return 0; 242 1.1 lukem } 243 1.1 lukem 244 1.1 lukem static struct berval *passwd_scheme( 245 1.1 lukem const struct pw_scheme *scheme, 246 1.1 lukem const struct berval * passwd, 247 1.1 lukem struct berval *bv, 248 1.1 lukem const char** allowed ) 249 1.1 lukem { 250 1.1 lukem if( !is_allowed_scheme( scheme->name.bv_val, allowed ) ) { 251 1.1 lukem return NULL; 252 1.1 lukem } 253 1.1 lukem 254 1.1 lukem if( passwd->bv_len >= scheme->name.bv_len ) { 255 1.1 lukem if( strncasecmp( passwd->bv_val, scheme->name.bv_val, scheme->name.bv_len ) == 0 ) { 256 1.1 lukem bv->bv_val = &passwd->bv_val[scheme->name.bv_len]; 257 1.1 lukem bv->bv_len = passwd->bv_len - scheme->name.bv_len; 258 1.1 lukem 259 1.1 lukem return bv; 260 1.1 lukem } 261 1.1 lukem } 262 1.1 lukem 263 1.1 lukem return NULL; 264 1.1 lukem } 265 1.1 lukem 266 1.1 lukem /* 267 1.1 lukem * Return 0 if creds are good. 268 1.1 lukem */ 269 1.1 lukem int 270 1.1 lukem lutil_passwd( 271 1.1 lukem const struct berval *passwd, /* stored passwd */ 272 1.1 lukem const struct berval *cred, /* user cred */ 273 1.1 lukem const char **schemes, 274 1.1 lukem const char **text ) 275 1.1 lukem { 276 1.1 lukem struct pw_slist *pws; 277 1.1 lukem 278 1.1 lukem if ( text ) *text = NULL; 279 1.1 lukem 280 1.1 lukem if (cred == NULL || cred->bv_len == 0 || 281 1.1 lukem passwd == NULL || passwd->bv_len == 0 ) 282 1.1 lukem { 283 1.1 lukem return -1; 284 1.1 lukem } 285 1.1 lukem 286 1.1 lukem if (!pw_inited) lutil_passwd_init(); 287 1.1 lukem 288 1.1 lukem for( pws=pw_schemes; pws; pws=pws->next ) { 289 1.1 lukem if( pws->s.chk_fn ) { 290 1.1 lukem struct berval x; 291 1.1 lukem struct berval *p = passwd_scheme( &(pws->s), 292 1.1 lukem passwd, &x, schemes ); 293 1.1 lukem 294 1.1 lukem if( p != NULL ) { 295 1.1 lukem return (pws->s.chk_fn)( &(pws->s.name), p, cred, text ); 296 1.1 lukem } 297 1.1 lukem } 298 1.1 lukem } 299 1.1 lukem 300 1.1 lukem #ifdef SLAPD_CLEARTEXT 301 1.1 lukem /* Do we think there is a scheme specifier here that we 302 1.1 lukem * didn't recognize? Assume a scheme name is at least 1 character. 303 1.1 lukem */ 304 1.1 lukem if (( passwd->bv_val[0] == '{' ) && 305 1.1 lukem ( ber_bvchr( passwd, '}' ) > passwd->bv_val+1 )) 306 1.1 lukem { 307 1.1 lukem return 1; 308 1.1 lukem } 309 1.1 lukem if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) { 310 1.1 lukem return ( passwd->bv_len == cred->bv_len ) ? 311 1.1 lukem memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len ) 312 1.1 lukem : 1; 313 1.1 lukem } 314 1.1 lukem #endif 315 1.1 lukem return 1; 316 1.1 lukem } 317 1.1 lukem 318 1.1 lukem int lutil_passwd_generate( struct berval *pw, ber_len_t len ) 319 1.1 lukem { 320 1.1 lukem 321 1.1 lukem if( len < 1 ) return -1; 322 1.1 lukem 323 1.1 lukem pw->bv_len = len; 324 1.1 lukem pw->bv_val = ber_memalloc( len + 1 ); 325 1.1 lukem 326 1.1 lukem if( pw->bv_val == NULL ) { 327 1.1 lukem return -1; 328 1.1 lukem } 329 1.1 lukem 330 1.1 lukem if( lutil_entropy( (unsigned char *) pw->bv_val, pw->bv_len) < 0 ) { 331 1.1 lukem return -1; 332 1.1 lukem } 333 1.1 lukem 334 1.1 lukem for( len = 0; len < pw->bv_len; len++ ) { 335 1.1 lukem pw->bv_val[len] = crypt64[ 336 1.1 lukem pw->bv_val[len] % (sizeof(crypt64)-1) ]; 337 1.1 lukem } 338 1.1 lukem 339 1.1 lukem pw->bv_val[len] = '\0'; 340 1.1 lukem 341 1.1 lukem return 0; 342 1.1 lukem } 343 1.1 lukem 344 1.1 lukem int lutil_passwd_hash( 345 1.1 lukem const struct berval * passwd, 346 1.1 lukem const char * method, 347 1.1 lukem struct berval *hash, 348 1.1 lukem const char **text ) 349 1.1 lukem { 350 1.1 lukem const struct pw_scheme *sc = get_scheme( method ); 351 1.1 lukem 352 1.1 lukem hash->bv_val = NULL; 353 1.1 lukem hash->bv_len = 0; 354 1.1 lukem 355 1.1 lukem if( sc == NULL ) { 356 1.1 lukem if( text ) *text = "scheme not recognized"; 357 1.1 lukem return -1; 358 1.1 lukem } 359 1.1 lukem 360 1.1 lukem if( ! sc->hash_fn ) { 361 1.1 lukem if( text ) *text = "scheme provided no hash function"; 362 1.1 lukem return -1; 363 1.1 lukem } 364 1.1 lukem 365 1.1 lukem if( text ) *text = NULL; 366 1.1 lukem 367 1.1 lukem return (sc->hash_fn)( &sc->name, passwd, hash, text ); 368 1.1 lukem } 369 1.1 lukem 370 1.9 christos /* pw_string is only called when SLAPD_CRYPT is defined */ 371 1.9 christos #if defined(SLAPD_CRYPT) 372 1.1 lukem static int pw_string( 373 1.1 lukem const struct berval *sc, 374 1.1 lukem struct berval *passwd ) 375 1.1 lukem { 376 1.1 lukem struct berval pw; 377 1.1 lukem 378 1.1 lukem pw.bv_len = sc->bv_len + passwd->bv_len; 379 1.1 lukem pw.bv_val = ber_memalloc( pw.bv_len + 1 ); 380 1.1 lukem 381 1.1 lukem if( pw.bv_val == NULL ) { 382 1.1 lukem return LUTIL_PASSWD_ERR; 383 1.1 lukem } 384 1.1 lukem 385 1.1 lukem AC_MEMCPY( pw.bv_val, sc->bv_val, sc->bv_len ); 386 1.1 lukem AC_MEMCPY( &pw.bv_val[sc->bv_len], passwd->bv_val, passwd->bv_len ); 387 1.1 lukem 388 1.1 lukem pw.bv_val[pw.bv_len] = '\0'; 389 1.1 lukem *passwd = pw; 390 1.1 lukem 391 1.1 lukem return LUTIL_PASSWD_OK; 392 1.1 lukem } 393 1.9 christos #endif /* SLAPD_CRYPT */ 394 1.1 lukem 395 1.4 tron int lutil_passwd_string64( 396 1.1 lukem const struct berval *sc, 397 1.1 lukem const struct berval *hash, 398 1.1 lukem struct berval *b64, 399 1.1 lukem const struct berval *salt ) 400 1.1 lukem { 401 1.1 lukem int rc; 402 1.1 lukem struct berval string; 403 1.1 lukem size_t b64len; 404 1.1 lukem 405 1.1 lukem if( salt ) { 406 1.1 lukem /* need to base64 combined string */ 407 1.1 lukem string.bv_len = hash->bv_len + salt->bv_len; 408 1.1 lukem string.bv_val = ber_memalloc( string.bv_len + 1 ); 409 1.1 lukem 410 1.1 lukem if( string.bv_val == NULL ) { 411 1.1 lukem return LUTIL_PASSWD_ERR; 412 1.1 lukem } 413 1.1 lukem 414 1.1 lukem AC_MEMCPY( string.bv_val, hash->bv_val, 415 1.1 lukem hash->bv_len ); 416 1.1 lukem AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val, 417 1.1 lukem salt->bv_len ); 418 1.1 lukem string.bv_val[string.bv_len] = '\0'; 419 1.1 lukem 420 1.1 lukem } else { 421 1.1 lukem string = *hash; 422 1.1 lukem } 423 1.1 lukem 424 1.1 lukem b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1; 425 1.1 lukem b64->bv_len = b64len + sc->bv_len; 426 1.1 lukem b64->bv_val = ber_memalloc( b64->bv_len + 1 ); 427 1.1 lukem 428 1.1 lukem if( b64->bv_val == NULL ) { 429 1.1 lukem if( salt ) ber_memfree( string.bv_val ); 430 1.1 lukem return LUTIL_PASSWD_ERR; 431 1.1 lukem } 432 1.1 lukem 433 1.1 lukem AC_MEMCPY(b64->bv_val, sc->bv_val, sc->bv_len); 434 1.1 lukem 435 1.1 lukem rc = lutil_b64_ntop( 436 1.1 lukem (unsigned char *) string.bv_val, string.bv_len, 437 1.1 lukem &b64->bv_val[sc->bv_len], b64len ); 438 1.1 lukem 439 1.1 lukem if( salt ) ber_memfree( string.bv_val ); 440 1.1 lukem 441 1.1 lukem if( rc < 0 ) { 442 1.1 lukem return LUTIL_PASSWD_ERR; 443 1.1 lukem } 444 1.1 lukem 445 1.1 lukem /* recompute length */ 446 1.1 lukem b64->bv_len = sc->bv_len + rc; 447 1.1 lukem assert( strlen(b64->bv_val) == b64->bv_len ); 448 1.1 lukem return LUTIL_PASSWD_OK; 449 1.1 lukem } 450 1.1 lukem 451 1.1 lukem /* PASSWORD CHECK ROUTINES */ 452 1.1 lukem 453 1.1 lukem #ifdef LUTIL_SHA1_BYTES 454 1.1 lukem static int chk_ssha1( 455 1.1 lukem const struct berval *sc, 456 1.1 lukem const struct berval * passwd, 457 1.1 lukem const struct berval * cred, 458 1.1 lukem const char **text ) 459 1.1 lukem { 460 1.1 lukem lutil_SHA1_CTX SHA1context; 461 1.1 lukem unsigned char SHA1digest[LUTIL_SHA1_BYTES]; 462 1.1 lukem int rc; 463 1.1 lukem unsigned char *orig_pass = NULL; 464 1.5 christos size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len); 465 1.1 lukem 466 1.1 lukem /* safety check -- must have some salt */ 467 1.5 christos if (decode_len <= sizeof(SHA1digest)) { 468 1.1 lukem return LUTIL_PASSWD_ERR; 469 1.1 lukem } 470 1.1 lukem 471 1.1 lukem /* decode base64 password */ 472 1.5 christos orig_pass = (unsigned char *) ber_memalloc(decode_len + 1); 473 1.1 lukem 474 1.1 lukem if( orig_pass == NULL ) return LUTIL_PASSWD_ERR; 475 1.1 lukem 476 1.5 christos rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len); 477 1.1 lukem 478 1.1 lukem /* safety check -- must have some salt */ 479 1.1 lukem if (rc <= (int)(sizeof(SHA1digest))) { 480 1.1 lukem ber_memfree(orig_pass); 481 1.1 lukem return LUTIL_PASSWD_ERR; 482 1.1 lukem } 483 1.1 lukem 484 1.1 lukem /* hash credentials with salt */ 485 1.1 lukem lutil_SHA1Init(&SHA1context); 486 1.1 lukem lutil_SHA1Update(&SHA1context, 487 1.1 lukem (const unsigned char *) cred->bv_val, cred->bv_len); 488 1.1 lukem lutil_SHA1Update(&SHA1context, 489 1.1 lukem (const unsigned char *) &orig_pass[sizeof(SHA1digest)], 490 1.1 lukem rc - sizeof(SHA1digest)); 491 1.1 lukem lutil_SHA1Final(SHA1digest, &SHA1context); 492 1.1 lukem 493 1.1 lukem /* compare */ 494 1.1 lukem rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest)); 495 1.1 lukem ber_memfree(orig_pass); 496 1.1 lukem return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; 497 1.1 lukem } 498 1.1 lukem 499 1.1 lukem static int chk_sha1( 500 1.1 lukem const struct berval *sc, 501 1.1 lukem const struct berval * passwd, 502 1.1 lukem const struct berval * cred, 503 1.1 lukem const char **text ) 504 1.1 lukem { 505 1.1 lukem lutil_SHA1_CTX SHA1context; 506 1.1 lukem unsigned char SHA1digest[LUTIL_SHA1_BYTES]; 507 1.1 lukem int rc; 508 1.1 lukem unsigned char *orig_pass = NULL; 509 1.5 christos size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len); 510 1.1 lukem 511 1.1 lukem /* safety check */ 512 1.5 christos if (decode_len < sizeof(SHA1digest)) { 513 1.1 lukem return LUTIL_PASSWD_ERR; 514 1.1 lukem } 515 1.1 lukem 516 1.1 lukem /* base64 un-encode password */ 517 1.5 christos orig_pass = (unsigned char *) ber_memalloc(decode_len + 1); 518 1.1 lukem 519 1.1 lukem if( orig_pass == NULL ) return LUTIL_PASSWD_ERR; 520 1.1 lukem 521 1.5 christos rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len); 522 1.1 lukem 523 1.1 lukem if( rc != sizeof(SHA1digest) ) { 524 1.1 lukem ber_memfree(orig_pass); 525 1.1 lukem return LUTIL_PASSWD_ERR; 526 1.1 lukem } 527 1.1 lukem 528 1.1 lukem /* hash credentials with salt */ 529 1.1 lukem lutil_SHA1Init(&SHA1context); 530 1.1 lukem lutil_SHA1Update(&SHA1context, 531 1.1 lukem (const unsigned char *) cred->bv_val, cred->bv_len); 532 1.1 lukem lutil_SHA1Final(SHA1digest, &SHA1context); 533 1.1 lukem 534 1.1 lukem /* compare */ 535 1.1 lukem rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest)); 536 1.1 lukem ber_memfree(orig_pass); 537 1.1 lukem return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; 538 1.1 lukem } 539 1.1 lukem #endif 540 1.1 lukem 541 1.1 lukem static int chk_smd5( 542 1.1 lukem const struct berval *sc, 543 1.1 lukem const struct berval * passwd, 544 1.1 lukem const struct berval * cred, 545 1.1 lukem const char **text ) 546 1.1 lukem { 547 1.1 lukem lutil_MD5_CTX MD5context; 548 1.1 lukem unsigned char MD5digest[LUTIL_MD5_BYTES]; 549 1.1 lukem int rc; 550 1.1 lukem unsigned char *orig_pass = NULL; 551 1.5 christos size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len); 552 1.1 lukem 553 1.1 lukem /* safety check */ 554 1.5 christos if (decode_len <= sizeof(MD5digest)) { 555 1.1 lukem return LUTIL_PASSWD_ERR; 556 1.1 lukem } 557 1.1 lukem 558 1.1 lukem /* base64 un-encode password */ 559 1.5 christos orig_pass = (unsigned char *) ber_memalloc(decode_len + 1); 560 1.1 lukem 561 1.1 lukem if( orig_pass == NULL ) return LUTIL_PASSWD_ERR; 562 1.1 lukem 563 1.5 christos rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len); 564 1.1 lukem 565 1.1 lukem if (rc <= (int)(sizeof(MD5digest))) { 566 1.1 lukem ber_memfree(orig_pass); 567 1.1 lukem return LUTIL_PASSWD_ERR; 568 1.1 lukem } 569 1.1 lukem 570 1.1 lukem /* hash credentials with salt */ 571 1.1 lukem lutil_MD5Init(&MD5context); 572 1.1 lukem lutil_MD5Update(&MD5context, 573 1.1 lukem (const unsigned char *) cred->bv_val, 574 1.1 lukem cred->bv_len ); 575 1.1 lukem lutil_MD5Update(&MD5context, 576 1.1 lukem &orig_pass[sizeof(MD5digest)], 577 1.1 lukem rc - sizeof(MD5digest)); 578 1.1 lukem lutil_MD5Final(MD5digest, &MD5context); 579 1.1 lukem 580 1.1 lukem /* compare */ 581 1.1 lukem rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest)); 582 1.1 lukem ber_memfree(orig_pass); 583 1.1 lukem return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; 584 1.1 lukem } 585 1.1 lukem 586 1.1 lukem static int chk_md5( 587 1.1 lukem const struct berval *sc, 588 1.1 lukem const struct berval * passwd, 589 1.1 lukem const struct berval * cred, 590 1.1 lukem const char **text ) 591 1.1 lukem { 592 1.1 lukem lutil_MD5_CTX MD5context; 593 1.1 lukem unsigned char MD5digest[LUTIL_MD5_BYTES]; 594 1.1 lukem int rc; 595 1.1 lukem unsigned char *orig_pass = NULL; 596 1.5 christos size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len); 597 1.1 lukem 598 1.1 lukem /* safety check */ 599 1.5 christos if (decode_len < sizeof(MD5digest)) { 600 1.1 lukem return LUTIL_PASSWD_ERR; 601 1.1 lukem } 602 1.1 lukem 603 1.1 lukem /* base64 un-encode password */ 604 1.5 christos orig_pass = (unsigned char *) ber_memalloc(decode_len + 1); 605 1.1 lukem 606 1.1 lukem if( orig_pass == NULL ) return LUTIL_PASSWD_ERR; 607 1.1 lukem 608 1.5 christos rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len); 609 1.1 lukem if ( rc != sizeof(MD5digest) ) { 610 1.1 lukem ber_memfree(orig_pass); 611 1.1 lukem return LUTIL_PASSWD_ERR; 612 1.1 lukem } 613 1.1 lukem 614 1.1 lukem /* hash credentials with salt */ 615 1.1 lukem lutil_MD5Init(&MD5context); 616 1.1 lukem lutil_MD5Update(&MD5context, 617 1.1 lukem (const unsigned char *) cred->bv_val, 618 1.1 lukem cred->bv_len ); 619 1.1 lukem lutil_MD5Final(MD5digest, &MD5context); 620 1.1 lukem 621 1.1 lukem /* compare */ 622 1.1 lukem rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest)); 623 1.1 lukem ber_memfree(orig_pass); 624 1.1 lukem return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; 625 1.1 lukem } 626 1.1 lukem 627 1.1 lukem #ifdef SLAPD_CRYPT 628 1.1 lukem static int lutil_crypt( 629 1.1 lukem const char *key, 630 1.1 lukem const char *salt, 631 1.1 lukem char **hash ) 632 1.1 lukem { 633 1.1 lukem char *cr = crypt( key, salt ); 634 1.1 lukem int rc; 635 1.1 lukem 636 1.1 lukem if( cr == NULL || cr[0] == '\0' ) { 637 1.1 lukem /* salt must have been invalid */ 638 1.1 lukem rc = LUTIL_PASSWD_ERR; 639 1.1 lukem } else { 640 1.1 lukem if ( hash ) { 641 1.1 lukem *hash = ber_strdup( cr ); 642 1.1 lukem rc = LUTIL_PASSWD_OK; 643 1.1 lukem } else { 644 1.1 lukem rc = strcmp( salt, cr ) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; 645 1.1 lukem } 646 1.1 lukem } 647 1.1 lukem return rc; 648 1.1 lukem } 649 1.1 lukem 650 1.1 lukem static int chk_crypt( 651 1.1 lukem const struct berval *sc, 652 1.1 lukem const struct berval * passwd, 653 1.1 lukem const struct berval * cred, 654 1.1 lukem const char **text ) 655 1.1 lukem { 656 1.1 lukem unsigned int i; 657 1.1 lukem 658 1.1 lukem for( i=0; i<cred->bv_len; i++) { 659 1.1 lukem if(cred->bv_val[i] == '\0') { 660 1.1 lukem return LUTIL_PASSWD_ERR; /* NUL character in password */ 661 1.1 lukem } 662 1.1 lukem } 663 1.1 lukem 664 1.1 lukem if( cred->bv_val[i] != '\0' ) { 665 1.1 lukem return LUTIL_PASSWD_ERR; /* cred must behave like a string */ 666 1.1 lukem } 667 1.1 lukem 668 1.1 lukem if( passwd->bv_len < 2 ) { 669 1.1 lukem return LUTIL_PASSWD_ERR; /* passwd must be at least two characters long */ 670 1.1 lukem } 671 1.1 lukem 672 1.1 lukem for( i=0; i<passwd->bv_len; i++) { 673 1.1 lukem if(passwd->bv_val[i] == '\0') { 674 1.1 lukem return LUTIL_PASSWD_ERR; /* NUL character in password */ 675 1.1 lukem } 676 1.1 lukem } 677 1.1 lukem 678 1.1 lukem if( passwd->bv_val[i] != '\0' ) { 679 1.1 lukem return LUTIL_PASSWD_ERR; /* passwd must behave like a string */ 680 1.1 lukem } 681 1.1 lukem 682 1.1 lukem return lutil_cryptptr( cred->bv_val, passwd->bv_val, NULL ); 683 1.1 lukem } 684 1.1 lukem 685 1.1 lukem # if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) 686 1.1 lukem static int chk_unix( 687 1.1 lukem const struct berval *sc, 688 1.1 lukem const struct berval * passwd, 689 1.1 lukem const struct berval * cred, 690 1.1 lukem const char **text ) 691 1.1 lukem { 692 1.1 lukem unsigned int i; 693 1.1 lukem char *pw; 694 1.1 lukem 695 1.1 lukem for( i=0; i<cred->bv_len; i++) { 696 1.1 lukem if(cred->bv_val[i] == '\0') { 697 1.1 lukem return LUTIL_PASSWD_ERR; /* NUL character in password */ 698 1.1 lukem } 699 1.1 lukem } 700 1.1 lukem if( cred->bv_val[i] != '\0' ) { 701 1.1 lukem return LUTIL_PASSWD_ERR; /* cred must behave like a string */ 702 1.1 lukem } 703 1.1 lukem 704 1.1 lukem for( i=0; i<passwd->bv_len; i++) { 705 1.1 lukem if(passwd->bv_val[i] == '\0') { 706 1.1 lukem return LUTIL_PASSWD_ERR; /* NUL character in password */ 707 1.1 lukem } 708 1.1 lukem } 709 1.1 lukem 710 1.1 lukem if( passwd->bv_val[i] != '\0' ) { 711 1.1 lukem return LUTIL_PASSWD_ERR; /* passwd must behave like a string */ 712 1.1 lukem } 713 1.1 lukem 714 1.1 lukem { 715 1.1 lukem struct passwd *pwd = getpwnam(passwd->bv_val); 716 1.1 lukem 717 1.1 lukem if(pwd == NULL) { 718 1.1 lukem return LUTIL_PASSWD_ERR; /* not found */ 719 1.1 lukem } 720 1.1 lukem 721 1.1 lukem pw = pwd->pw_passwd; 722 1.1 lukem } 723 1.1 lukem # ifdef HAVE_GETSPNAM 724 1.1 lukem { 725 1.1 lukem struct spwd *spwd = getspnam(passwd->bv_val); 726 1.1 lukem 727 1.1 lukem if(spwd != NULL) { 728 1.1 lukem pw = spwd->sp_pwdp; 729 1.1 lukem } 730 1.1 lukem } 731 1.1 lukem # endif 732 1.1 lukem # ifdef HAVE_AIX_SECURITY 733 1.1 lukem { 734 1.1 lukem struct userpw *upw = getuserpw(passwd->bv_val); 735 1.1 lukem 736 1.1 lukem if (upw != NULL) { 737 1.1 lukem pw = upw->upw_passwd; 738 1.1 lukem } 739 1.1 lukem } 740 1.1 lukem # endif 741 1.1 lukem 742 1.1 lukem if( pw == NULL || pw[0] == '\0' || pw[1] == '\0' ) { 743 1.1 lukem /* password must must be at least two characters long */ 744 1.1 lukem return LUTIL_PASSWD_ERR; 745 1.1 lukem } 746 1.1 lukem 747 1.1 lukem return lutil_cryptptr( cred->bv_val, pw, NULL ); 748 1.1 lukem } 749 1.1 lukem # endif 750 1.1 lukem #endif 751 1.1 lukem 752 1.1 lukem /* PASSWORD GENERATION ROUTINES */ 753 1.1 lukem 754 1.1 lukem #ifdef LUTIL_SHA1_BYTES 755 1.1 lukem static int hash_ssha1( 756 1.1 lukem const struct berval *scheme, 757 1.1 lukem const struct berval *passwd, 758 1.1 lukem struct berval *hash, 759 1.1 lukem const char **text ) 760 1.1 lukem { 761 1.1 lukem lutil_SHA1_CTX SHA1context; 762 1.1 lukem unsigned char SHA1digest[LUTIL_SHA1_BYTES]; 763 1.1 lukem char saltdata[SALT_SIZE]; 764 1.1 lukem struct berval digest; 765 1.1 lukem struct berval salt; 766 1.1 lukem 767 1.1 lukem digest.bv_val = (char *) SHA1digest; 768 1.1 lukem digest.bv_len = sizeof(SHA1digest); 769 1.1 lukem salt.bv_val = saltdata; 770 1.1 lukem salt.bv_len = sizeof(saltdata); 771 1.1 lukem 772 1.1 lukem if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) { 773 1.1 lukem return LUTIL_PASSWD_ERR; 774 1.1 lukem } 775 1.1 lukem 776 1.1 lukem lutil_SHA1Init( &SHA1context ); 777 1.1 lukem lutil_SHA1Update( &SHA1context, 778 1.1 lukem (const unsigned char *)passwd->bv_val, passwd->bv_len ); 779 1.1 lukem lutil_SHA1Update( &SHA1context, 780 1.1 lukem (const unsigned char *)salt.bv_val, salt.bv_len ); 781 1.1 lukem lutil_SHA1Final( SHA1digest, &SHA1context ); 782 1.1 lukem 783 1.4 tron return lutil_passwd_string64( scheme, &digest, hash, &salt); 784 1.1 lukem } 785 1.1 lukem 786 1.1 lukem static int hash_sha1( 787 1.1 lukem const struct berval *scheme, 788 1.1 lukem const struct berval *passwd, 789 1.1 lukem struct berval *hash, 790 1.1 lukem const char **text ) 791 1.1 lukem { 792 1.1 lukem lutil_SHA1_CTX SHA1context; 793 1.1 lukem unsigned char SHA1digest[LUTIL_SHA1_BYTES]; 794 1.1 lukem struct berval digest; 795 1.1 lukem digest.bv_val = (char *) SHA1digest; 796 1.1 lukem digest.bv_len = sizeof(SHA1digest); 797 1.1 lukem 798 1.1 lukem lutil_SHA1Init( &SHA1context ); 799 1.1 lukem lutil_SHA1Update( &SHA1context, 800 1.1 lukem (const unsigned char *)passwd->bv_val, passwd->bv_len ); 801 1.1 lukem lutil_SHA1Final( SHA1digest, &SHA1context ); 802 1.1 lukem 803 1.4 tron return lutil_passwd_string64( scheme, &digest, hash, NULL); 804 1.1 lukem } 805 1.1 lukem #endif 806 1.1 lukem 807 1.1 lukem static int hash_smd5( 808 1.1 lukem const struct berval *scheme, 809 1.1 lukem const struct berval *passwd, 810 1.1 lukem struct berval *hash, 811 1.1 lukem const char **text ) 812 1.1 lukem { 813 1.1 lukem lutil_MD5_CTX MD5context; 814 1.1 lukem unsigned char MD5digest[LUTIL_MD5_BYTES]; 815 1.1 lukem char saltdata[SALT_SIZE]; 816 1.1 lukem struct berval digest; 817 1.1 lukem struct berval salt; 818 1.1 lukem 819 1.1 lukem digest.bv_val = (char *) MD5digest; 820 1.1 lukem digest.bv_len = sizeof(MD5digest); 821 1.1 lukem salt.bv_val = saltdata; 822 1.1 lukem salt.bv_len = sizeof(saltdata); 823 1.1 lukem 824 1.1 lukem if( lutil_entropy( (unsigned char *) salt.bv_val, salt.bv_len) < 0 ) { 825 1.1 lukem return LUTIL_PASSWD_ERR; 826 1.1 lukem } 827 1.1 lukem 828 1.1 lukem lutil_MD5Init( &MD5context ); 829 1.1 lukem lutil_MD5Update( &MD5context, 830 1.1 lukem (const unsigned char *) passwd->bv_val, passwd->bv_len ); 831 1.1 lukem lutil_MD5Update( &MD5context, 832 1.1 lukem (const unsigned char *) salt.bv_val, salt.bv_len ); 833 1.1 lukem lutil_MD5Final( MD5digest, &MD5context ); 834 1.1 lukem 835 1.4 tron return lutil_passwd_string64( scheme, &digest, hash, &salt ); 836 1.1 lukem } 837 1.1 lukem 838 1.1 lukem static int hash_md5( 839 1.1 lukem const struct berval *scheme, 840 1.1 lukem const struct berval *passwd, 841 1.1 lukem struct berval *hash, 842 1.1 lukem const char **text ) 843 1.1 lukem { 844 1.1 lukem lutil_MD5_CTX MD5context; 845 1.1 lukem unsigned char MD5digest[LUTIL_MD5_BYTES]; 846 1.1 lukem 847 1.1 lukem struct berval digest; 848 1.1 lukem 849 1.1 lukem digest.bv_val = (char *) MD5digest; 850 1.1 lukem digest.bv_len = sizeof(MD5digest); 851 1.1 lukem 852 1.1 lukem lutil_MD5Init( &MD5context ); 853 1.1 lukem lutil_MD5Update( &MD5context, 854 1.1 lukem (const unsigned char *) passwd->bv_val, passwd->bv_len ); 855 1.1 lukem lutil_MD5Final( MD5digest, &MD5context ); 856 1.1 lukem 857 1.4 tron return lutil_passwd_string64( scheme, &digest, hash, NULL ); 858 1.1 lukem ; 859 1.1 lukem } 860 1.1 lukem 861 1.1 lukem #ifdef SLAPD_CRYPT 862 1.1 lukem static int hash_crypt( 863 1.1 lukem const struct berval *scheme, 864 1.1 lukem const struct berval *passwd, 865 1.1 lukem struct berval *hash, 866 1.1 lukem const char **text ) 867 1.1 lukem { 868 1.1 lukem unsigned char salt[32]; /* salt suitable for most anything */ 869 1.1 lukem unsigned int i; 870 1.1 lukem char *save; 871 1.1 lukem int rc; 872 1.1 lukem 873 1.1 lukem for( i=0; i<passwd->bv_len; i++) { 874 1.1 lukem if(passwd->bv_val[i] == '\0') { 875 1.1 lukem return LUTIL_PASSWD_ERR; /* NUL character in password */ 876 1.1 lukem } 877 1.1 lukem } 878 1.1 lukem 879 1.1 lukem if( passwd->bv_val[i] != '\0' ) { 880 1.1 lukem return LUTIL_PASSWD_ERR; /* passwd must behave like a string */ 881 1.1 lukem } 882 1.1 lukem 883 1.1 lukem if( lutil_entropy( salt, sizeof( salt ) ) < 0 ) { 884 1.1 lukem return LUTIL_PASSWD_ERR; 885 1.1 lukem } 886 1.1 lukem 887 1.1 lukem for( i=0; i< ( sizeof(salt) - 1 ); i++ ) { 888 1.1 lukem salt[i] = crypt64[ salt[i] % (sizeof(crypt64)-1) ]; 889 1.1 lukem } 890 1.1 lukem salt[sizeof( salt ) - 1 ] = '\0'; 891 1.1 lukem 892 1.1 lukem if( salt_format != NULL ) { 893 1.1 lukem /* copy the salt we made into entropy before snprintfing 894 1.1 lukem it back into the salt */ 895 1.1 lukem char entropy[sizeof(salt)]; 896 1.1 lukem strcpy( entropy, (char *) salt ); 897 1.1 lukem snprintf( (char *) salt, sizeof(entropy), salt_format, entropy ); 898 1.1 lukem } 899 1.1 lukem 900 1.1 lukem rc = lutil_cryptptr( passwd->bv_val, (char *) salt, &hash->bv_val ); 901 1.1 lukem if ( rc != LUTIL_PASSWD_OK ) return rc; 902 1.1 lukem 903 1.1 lukem if( hash->bv_val == NULL ) return -1; 904 1.1 lukem 905 1.1 lukem hash->bv_len = strlen( hash->bv_val ); 906 1.1 lukem 907 1.1 lukem save = hash->bv_val; 908 1.1 lukem 909 1.1 lukem if( hash->bv_len == 0 ) { 910 1.1 lukem rc = LUTIL_PASSWD_ERR; 911 1.1 lukem } else { 912 1.1 lukem rc = pw_string( scheme, hash ); 913 1.1 lukem } 914 1.1 lukem ber_memfree( save ); 915 1.1 lukem return rc; 916 1.1 lukem } 917 1.1 lukem #endif 918 1.1 lukem 919 1.1 lukem int lutil_salt_format(const char *format) 920 1.1 lukem { 921 1.1 lukem #ifdef SLAPD_CRYPT 922 1.2 lukem ber_memfree( salt_format ); 923 1.1 lukem 924 1.1 lukem salt_format = format != NULL ? ber_strdup( format ) : NULL; 925 1.1 lukem #endif 926 1.1 lukem 927 1.1 lukem return 0; 928 1.1 lukem } 929 1.1 lukem 930 1.1 lukem #ifdef SLAPD_CLEARTEXT 931 1.1 lukem static int hash_clear( 932 1.1 lukem const struct berval *scheme, 933 1.1 lukem const struct berval *passwd, 934 1.1 lukem struct berval *hash, 935 1.1 lukem const char **text ) 936 1.1 lukem { 937 1.1 lukem ber_dupbv( hash, (struct berval *)passwd ); 938 1.1 lukem return LUTIL_PASSWD_OK; 939 1.1 lukem } 940 1.1 lukem #endif 941 1.1 lukem 942