1 /* $NetBSD: slapd-totp.c,v 1.2 2021/08/14 16:14:53 christos Exp $ */ 2 3 /* slapd-totp.c - Password module and overlay for TOTP */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2015-2021 The OpenLDAP Foundation. 8 * Portions Copyright 2015 by Howard Chu, Symas Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 /* ACKNOWLEDGEMENTS: 20 * This work includes code from the lastbind overlay. 21 */ 22 23 #include <portable.h> 24 25 #if HAVE_STDINT_H 26 #include <stdint.h> 27 #endif 28 29 #include <lber.h> 30 #include <lber_pvt.h> 31 #include "lutil.h" 32 #include <ac/stdlib.h> 33 #include <ac/ctype.h> 34 #include <ac/string.h> 35 /* include socket.h to get sys/types.h and/or winsock2.h */ 36 #include <ac/socket.h> 37 38 #if HAVE_OPENSSL 39 #include <openssl/sha.h> 40 #include <openssl/hmac.h> 41 42 #define TOTP_SHA512_DIGEST_LENGTH SHA512_DIGEST_LENGTH 43 #define TOTP_SHA1 EVP_sha1() 44 #define TOTP_SHA256 EVP_sha256() 45 #define TOTP_SHA512 EVP_sha512() 46 #define TOTP_HMAC_CTX HMAC_CTX * 47 48 #if OPENSSL_VERSION_NUMBER < 0x10100000L 49 static HMAC_CTX *HMAC_CTX_new(void) 50 { 51 HMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx)); 52 if (ctx != NULL) { 53 HMAC_CTX_init(ctx); 54 } 55 return ctx; 56 } 57 58 static void HMAC_CTX_free(HMAC_CTX *ctx) 59 { 60 if (ctx != NULL) { 61 HMAC_CTX_cleanup(ctx); 62 OPENSSL_free(ctx); 63 } 64 } 65 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ 66 67 #define HMAC_setup(ctx, key, len, hash) \ 68 ctx = HMAC_CTX_new(); \ 69 HMAC_Init_ex(ctx, key, len, hash, 0) 70 #define HMAC_crunch(ctx, buf, len) HMAC_Update(ctx, buf, len) 71 #define HMAC_finish(ctx, dig, dlen) \ 72 HMAC_Final(ctx, dig, &dlen); \ 73 HMAC_CTX_free(ctx) 74 75 #elif HAVE_GNUTLS 76 #include <nettle/hmac.h> 77 78 #define TOTP_SHA512_DIGEST_LENGTH SHA512_DIGEST_SIZE 79 #define TOTP_SHA1 &nettle_sha1 80 #define TOTP_SHA256 &nettle_sha256 81 #define TOTP_SHA512 &nettle_sha512 82 #define TOTP_HMAC_CTX struct hmac_sha512_ctx 83 84 #define HMAC_setup(ctx, key, len, hash) \ 85 const struct nettle_hash *h=hash;\ 86 hmac_set_key(&ctx.outer, &ctx.inner, &ctx.state, h, len, key) 87 #define HMAC_crunch(ctx, buf, len) hmac_update(&ctx.state, h, len, buf) 88 #define HMAC_finish(ctx, dig, dlen) \ 89 hmac_digest(&ctx.outer, &ctx.inner, &ctx.state, h, h->digest_size, dig);\ 90 dlen = h->digest_size 91 92 #else 93 # error Unsupported crypto backend. 94 #endif 95 96 #include "slap.h" 97 #include "slap-config.h" 98 99 static LUTIL_PASSWD_CHK_FUNC chk_totp1, chk_totp256, chk_totp512, 100 chk_totp1andpw, chk_totp256andpw, chk_totp512andpw; 101 static LUTIL_PASSWD_HASH_FUNC hash_totp1, hash_totp256, hash_totp512, 102 hash_totp1andpw, hash_totp256andpw, hash_totp512andpw; 103 static const struct berval scheme_totp1 = BER_BVC("{TOTP1}"); 104 static const struct berval scheme_totp256 = BER_BVC("{TOTP256}"); 105 static const struct berval scheme_totp512 = BER_BVC("{TOTP512}"); 106 static const struct berval scheme_totp1andpw = BER_BVC("{TOTP1ANDPW}"); 107 static const struct berval scheme_totp256andpw = BER_BVC("{TOTP256ANDPW}"); 108 static const struct berval scheme_totp512andpw = BER_BVC("{TOTP512ANDPW}"); 109 110 static AttributeDescription *ad_authTimestamp; 111 112 /* This is the definition used by ISODE, as supplied to us in 113 * ITS#6238 Followup #9 114 */ 115 static struct schema_info { 116 char *def; 117 AttributeDescription **ad; 118 } totp_OpSchema[] = { 119 { "( 1.3.6.1.4.1.453.16.2.188 " 120 "NAME 'authTimestamp' " 121 "DESC 'last successful authentication using any method/mech' " 122 "EQUALITY generalizedTimeMatch " 123 "ORDERING generalizedTimeOrderingMatch " 124 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 " 125 "SINGLE-VALUE NO-USER-MODIFICATION USAGE dsaOperation )", 126 &ad_authTimestamp}, 127 { NULL, NULL } 128 }; 129 130 /* RFC3548 base32 encoding/decoding */ 131 132 static const char Base32[] = 133 "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 134 static const char Pad32 = '='; 135 136 static int 137 totp_b32_ntop( 138 u_char const *src, 139 size_t srclength, 140 char *target, 141 size_t targsize) 142 { 143 size_t datalength = 0; 144 u_char input0; 145 u_int input1; /* assumed to be at least 32 bits */ 146 u_char output[8]; 147 int i; 148 149 while (4 < srclength) { 150 if (datalength + 8 > targsize) 151 return (-1); 152 input0 = *src++; 153 input1 = *src++; 154 input1 <<= 8; 155 input1 |= *src++; 156 input1 <<= 8; 157 input1 |= *src++; 158 input1 <<= 8; 159 input1 |= *src++; 160 srclength -= 5; 161 162 for (i=7; i>1; i--) { 163 output[i] = input1 & 0x1f; 164 input1 >>= 5; 165 } 166 output[0] = input0 >> 3; 167 output[1] = (input0 & 0x07) << 2 | input1; 168 169 for (i=0; i<8; i++) 170 target[datalength++] = Base32[output[i]]; 171 } 172 173 /* Now we worry about padding. */ 174 if (0 != srclength) { 175 static const int outlen[] = { 2,4,5,7 }; 176 int n; 177 if (datalength + 8 > targsize) 178 return (-1); 179 180 /* Get what's left. */ 181 input1 = *src++; 182 for (i = 1; i < srclength; i++) { 183 input1 <<= 8; 184 input1 |= *src++; 185 } 186 input1 <<= 8 * (4-srclength); 187 n = outlen[srclength-1]; 188 for (i=0; i<n; i++) { 189 target[datalength++] = Base32[(input1 & 0xf8000000) >> 27]; 190 input1 <<= 5; 191 } 192 for (; i<8; i++) 193 target[datalength++] = Pad32; 194 } 195 if (datalength >= targsize) 196 return (-1); 197 target[datalength] = '\0'; /* Returned value doesn't count \0. */ 198 return (datalength); 199 } 200 201 /* converts characters, eight at a time, starting at src 202 from base - 32 numbers into five 8 bit bytes in the target area. 203 it returns the number of data bytes stored at the target, or -1 on error. 204 */ 205 206 static int 207 totp_b32_pton( 208 char const *src, 209 u_char *target, 210 size_t targsize) 211 { 212 int tarindex, state, ch; 213 char *pos; 214 215 state = 0; 216 tarindex = 0; 217 218 while ((ch = *src++) != '\0') { 219 if (ch == Pad32) 220 break; 221 222 pos = strchr(Base32, ch); 223 if (pos == 0) /* A non-base32 character. */ 224 return (-1); 225 226 switch (state) { 227 case 0: 228 if (target) { 229 if ((size_t)tarindex >= targsize) 230 return (-1); 231 target[tarindex] = (pos - Base32) << 3; 232 } 233 state = 1; 234 break; 235 case 1: 236 if (target) { 237 if ((size_t)tarindex + 1 >= targsize) 238 return (-1); 239 target[tarindex] |= (pos - Base32) >> 2; 240 target[tarindex+1] = ((pos - Base32) & 0x3) 241 << 6 ; 242 } 243 tarindex++; 244 state = 2; 245 break; 246 case 2: 247 if (target) { 248 target[tarindex] |= (pos - Base32) << 1; 249 } 250 state = 3; 251 break; 252 case 3: 253 if (target) { 254 if ((size_t)tarindex + 1 >= targsize) 255 return (-1); 256 target[tarindex] |= (pos - Base32) >> 4; 257 target[tarindex+1] = ((pos - Base32) & 0xf) 258 << 4 ; 259 } 260 tarindex++; 261 state = 4; 262 break; 263 case 4: 264 if (target) { 265 if ((size_t)tarindex + 1 >= targsize) 266 return (-1); 267 target[tarindex] |= (pos - Base32) >> 1; 268 target[tarindex+1] = ((pos - Base32) & 0x1) 269 << 7 ; 270 } 271 tarindex++; 272 state = 5; 273 break; 274 case 5: 275 if (target) { 276 target[tarindex] |= (pos - Base32) << 2; 277 } 278 state = 6; 279 break; 280 case 6: 281 if (target) { 282 if ((size_t)tarindex + 1 >= targsize) 283 return (-1); 284 target[tarindex] |= (pos - Base32) >> 3; 285 target[tarindex+1] = ((pos - Base32) & 0x7) 286 << 5 ; 287 } 288 tarindex++; 289 state = 7; 290 break; 291 case 7: 292 if (target) { 293 target[tarindex] |= (pos - Base32); 294 } 295 state = 0; 296 tarindex++; 297 break; 298 299 default: 300 abort(); 301 } 302 } 303 304 /* 305 * We are done decoding Base-32 chars. Let's see if we ended 306 * on a byte boundary, and/or with erroneous trailing characters. 307 */ 308 309 if (ch == Pad32) { /* We got a pad char. */ 310 int i = 0; 311 312 /* count pad chars */ 313 for (; ch; ch = *src++) { 314 if (ch != Pad32) 315 return (-1); 316 i++; 317 } 318 /* there are only 4 valid ending states with a 319 * pad character, make sure the number of pads is valid. 320 */ 321 switch(state) { 322 case 2: if (i != 6) return -1; 323 break; 324 case 4: if (i != 4) return -1; 325 break; 326 case 5: if (i != 3) return -1; 327 break; 328 case 7: if (i != 1) return -1; 329 break; 330 default: 331 return -1; 332 } 333 /* 334 * Now make sure that the "extra" bits that slopped past 335 * the last full byte were zeros. If we don't check them, 336 * they become a subliminal channel. 337 */ 338 if (target && target[tarindex] != 0) 339 return (-1); 340 } else { 341 /* 342 * We ended by seeing the end of the string. Make sure we 343 * have no partial bytes lying around. 344 */ 345 if (state != 0) 346 return (-1); 347 } 348 349 return (tarindex); 350 } 351 352 /* RFC6238 TOTP */ 353 354 355 typedef struct myval { 356 ber_len_t mv_len; 357 void *mv_val; 358 } myval; 359 360 static void do_hmac( 361 const void *hash, 362 myval *key, 363 myval *data, 364 myval *out) 365 { 366 TOTP_HMAC_CTX ctx; 367 unsigned int digestLen; 368 369 HMAC_setup(ctx, key->mv_val, key->mv_len, hash); 370 HMAC_crunch(ctx, data->mv_val, data->mv_len); 371 HMAC_finish(ctx, out->mv_val, digestLen); 372 out->mv_len = digestLen; 373 } 374 375 static const int DIGITS_POWER[] = { 376 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 }; 377 378 static void generate( 379 myval *key, 380 uint64_t tval, 381 int digits, 382 myval *out, 383 const void *mech) 384 { 385 unsigned char digest[TOTP_SHA512_DIGEST_LENGTH]; 386 myval digval; 387 myval data; 388 unsigned char msg[8]; 389 int i, offset, res, otp; 390 391 #if WORDS_BIGENDIAN 392 *(uint64_t *)msg = tval; 393 #else 394 for (i=7; i>=0; i--) { 395 msg[i] = tval & 0xff; 396 tval >>= 8; 397 } 398 #endif 399 400 data.mv_val = msg; 401 data.mv_len = sizeof(msg); 402 403 digval.mv_val = digest; 404 digval.mv_len = sizeof(digest); 405 do_hmac(mech, key, &data, &digval); 406 407 offset = digest[digval.mv_len-1] & 0xf; 408 res = ((digest[offset] & 0x7f) << 24) | 409 ((digest[offset+1] & 0xff) << 16) | 410 ((digest[offset+2] & 0xff) << 8) | 411 (digest[offset+3] & 0xff); 412 413 otp = res % DIGITS_POWER[digits]; 414 out->mv_len = snprintf(out->mv_val, out->mv_len, "%0*d", digits, otp); 415 } 416 417 static int totp_op_cleanup( Operation *op, SlapReply *rs ); 418 static int totp_bind_response( Operation *op, SlapReply *rs ); 419 420 #define TIME_STEP 30 421 #define DIGITS 6 422 #define DELIM '|' /* a single character */ 423 #define TOTP_AND_PW_HASH_SCHEME "{SSHA}" 424 425 static int chk_totp( 426 const struct berval *passwd, 427 const struct berval *cred, 428 const void *mech, 429 const char **text) 430 { 431 void *ctx, *op_tmp; 432 Operation *op; 433 Entry *e; 434 Attribute *a; 435 long t, told = 0; 436 int rc; 437 myval out, key; 438 char outbuf[32]; 439 440 /* Find our thread context, find our Operation */ 441 ctx = ldap_pvt_thread_pool_context(); 442 if (ldap_pvt_thread_pool_getkey(ctx, totp_op_cleanup, &op_tmp, NULL) || 443 !op_tmp) 444 return LUTIL_PASSWD_ERR; 445 op = op_tmp; 446 447 rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &e); 448 if (rc != LDAP_SUCCESS) return LUTIL_PASSWD_ERR; 449 450 /* Make sure previous login is older than current time */ 451 t = op->o_time / TIME_STEP; 452 a = attr_find(e->e_attrs, ad_authTimestamp); 453 if (a) { 454 struct lutil_tm tm; 455 struct lutil_timet tt; 456 if (lutil_parsetime(a->a_vals[0].bv_val, &tm) == 0 && 457 lutil_tm2time(&tm, &tt) == 0) { 458 told = tt.tt_sec / TIME_STEP; 459 if (told >= t) 460 rc = LUTIL_PASSWD_ERR; 461 } 462 if (!rc) { /* seems OK, remember old stamp */ 463 slap_callback *sc; 464 for (sc = op->o_callback; sc; sc = sc->sc_next) { 465 if (sc->sc_response == totp_bind_response) { 466 sc->sc_private = ber_dupbv_x(NULL, &a->a_vals[0], op->o_tmpmemctx); 467 break; 468 } 469 } 470 } 471 } /* else no previous login, 1st use is OK */ 472 473 be_entry_release_r(op, e); 474 if (rc) return rc; 475 476 /* Key is stored in base32 */ 477 key.mv_len = passwd->bv_len * 5 / 8; 478 key.mv_val = ber_memalloc(key.mv_len+1); 479 480 if (!key.mv_val) 481 return LUTIL_PASSWD_ERR; 482 483 rc = totp_b32_pton(passwd->bv_val, key.mv_val, key.mv_len); 484 if (rc < 1) { 485 rc = LUTIL_PASSWD_ERR; 486 goto out; 487 } 488 489 out.mv_val = outbuf; 490 out.mv_len = sizeof(outbuf); 491 generate(&key, t, DIGITS, &out, mech); 492 493 /* compare */ 494 if (out.mv_len != cred->bv_len) { 495 rc = LUTIL_PASSWD_ERR; 496 goto out; 497 } 498 499 rc = memcmp(out.mv_val, cred->bv_val, out.mv_len) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; 500 501 /* If current value doesn't match, try again with previous value 502 * but only if the most recent login is older than the previous 503 * time step but still set */ 504 if (rc == LUTIL_PASSWD_ERR && told < t - 1 && told > 0) { 505 out.mv_val = outbuf; 506 out.mv_len = sizeof(outbuf); 507 generate(&key, t - 1, DIGITS, &out, mech); 508 /* compare */ 509 if (out.mv_len != cred->bv_len) 510 goto out; 511 rc = memcmp(out.mv_val, cred->bv_val, out.mv_len) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; 512 } 513 514 out: 515 memset(key.mv_val, 0, key.mv_len); 516 ber_memfree(key.mv_val); 517 return rc; 518 } 519 520 static int chk_totp_and_pw( 521 const struct berval *scheme, 522 const struct berval *passwd, 523 const struct berval *cred, 524 const char **text, 525 const void *mech) 526 { 527 char *s; 528 int rc = LUTIL_PASSWD_ERR, rc_pass, rc_otp; 529 ber_len_t len; 530 struct berval cred_pass, cred_otp, passwd_pass, passwd_otp; 531 532 /* Check credential length, no point to continue if too short */ 533 if (cred->bv_len <= DIGITS) 534 return rc; 535 536 /* The OTP seed of the stored password */ 537 s = strchr(passwd->bv_val, DELIM); 538 if (s) { 539 len = s - passwd->bv_val; 540 } else { 541 return rc; 542 } 543 if (!ber_str2bv(passwd->bv_val, len, 1, &passwd_otp)) 544 return rc; 545 546 /* The password part of the stored password */ 547 s++; 548 ber_str2bv(s, 0, 0, &passwd_pass); 549 550 /* The OTP part of the entered credential */ 551 ber_str2bv(&cred->bv_val[cred->bv_len - DIGITS], DIGITS, 0, &cred_otp); 552 553 /* The password part of the entered credential */ 554 if (!ber_str2bv(cred->bv_val, cred->bv_len - DIGITS, 0, &cred_pass)) { 555 /* Cleanup */ 556 memset(passwd_otp.bv_val, 0, passwd_otp.bv_len); 557 ber_memfree(passwd_otp.bv_val); 558 return rc; 559 } 560 561 rc_otp = chk_totp(&passwd_otp, &cred_otp, mech, text); 562 rc_pass = lutil_passwd(&passwd_pass, &cred_pass, NULL, text); 563 if (rc_otp == LUTIL_PASSWD_OK && rc_pass == LUTIL_PASSWD_OK) 564 rc = LUTIL_PASSWD_OK; 565 566 /* Cleanup and return */ 567 memset(passwd_otp.bv_val, 0, passwd_otp.bv_len); 568 ber_memfree(passwd_otp.bv_val); 569 570 return rc; 571 } 572 573 static int chk_totp1( 574 const struct berval *scheme, 575 const struct berval *passwd, 576 const struct berval *cred, 577 const char **text) 578 { 579 return chk_totp(passwd, cred, TOTP_SHA1, text); 580 } 581 582 static int chk_totp256( 583 const struct berval *scheme, 584 const struct berval *passwd, 585 const struct berval *cred, 586 const char **text) 587 { 588 return chk_totp(passwd, cred, TOTP_SHA256, text); 589 } 590 591 static int chk_totp512( 592 const struct berval *scheme, 593 const struct berval *passwd, 594 const struct berval *cred, 595 const char **text) 596 { 597 return chk_totp(passwd, cred, TOTP_SHA512, text); 598 } 599 600 static int chk_totp1andpw( 601 const struct berval *scheme, 602 const struct berval *passwd, 603 const struct berval *cred, 604 const char **text) 605 { 606 return chk_totp_and_pw(scheme, passwd, cred, text, TOTP_SHA1); 607 } 608 609 static int chk_totp256andpw( 610 const struct berval *scheme, 611 const struct berval *passwd, 612 const struct berval *cred, 613 const char **text) 614 { 615 return chk_totp_and_pw(scheme, passwd, cred, text, TOTP_SHA256); 616 } 617 618 static int chk_totp512andpw( 619 const struct berval *scheme, 620 const struct berval *passwd, 621 const struct berval *cred, 622 const char **text) 623 { 624 return chk_totp_and_pw(scheme, passwd, cred, text, TOTP_SHA512); 625 } 626 627 static int passwd_string32( 628 const struct berval *scheme, 629 const struct berval *passwd, 630 struct berval *hash) 631 { 632 int b32len = (passwd->bv_len + 4)/5 * 8; 633 int rc; 634 hash->bv_len = scheme->bv_len + b32len; 635 hash->bv_val = ber_memalloc(hash->bv_len + 1); 636 AC_MEMCPY(hash->bv_val, scheme->bv_val, scheme->bv_len); 637 rc = totp_b32_ntop((unsigned char *)passwd->bv_val, passwd->bv_len, 638 hash->bv_val + scheme->bv_len, b32len+1); 639 if (rc < 0) { 640 ber_memfree(hash->bv_val); 641 hash->bv_val = NULL; 642 return LUTIL_PASSWD_ERR; 643 } 644 return LUTIL_PASSWD_OK; 645 } 646 647 static int hash_totp_and_pw( 648 const struct berval *scheme, 649 const struct berval *passwd, 650 struct berval *hash, 651 const char **text) 652 { 653 struct berval otp, pass, hash_otp, hash_pass; 654 ber_len_t len; 655 char *s; 656 int rc = LUTIL_PASSWD_ERR; 657 658 /* The OTP seed part */ 659 s = strchr(passwd->bv_val, DELIM); 660 if (s) { 661 len = s - passwd->bv_val; 662 } else { 663 return rc; 664 } 665 if (!ber_str2bv(passwd->bv_val, len, 0, &otp)) 666 return rc; 667 668 /* The static password part */ 669 s++; 670 ber_str2bv(s, 0, 0, &pass); 671 672 /* Hash the OTP seed */ 673 rc = passwd_string32(scheme, &otp, &hash_otp); 674 675 /* If successful, hash the static password, else cleanup and return */ 676 if (rc == LUTIL_PASSWD_OK) { 677 rc = lutil_passwd_hash(&pass, TOTP_AND_PW_HASH_SCHEME, 678 &hash_pass, text); 679 } else { 680 return LUTIL_PASSWD_ERR; 681 } 682 683 /* If successful, allocate memory to combine them, else cleanup 684 * and return */ 685 if (rc == LUTIL_PASSWD_OK) { 686 /* Add 1 character to bv_len to hold DELIM */ 687 hash->bv_len = hash_pass.bv_len + hash_otp.bv_len + 1; 688 hash->bv_val = ber_memalloc(hash->bv_len + 1); 689 if (!hash->bv_val) 690 rc = LUTIL_PASSWD_ERR; 691 } else { 692 memset(hash_otp.bv_val, 0, hash_otp.bv_len); 693 ber_memfree(hash_otp.bv_val); 694 return LUTIL_PASSWD_ERR; 695 } 696 697 /* If successful, combine the two hashes with the delimiter */ 698 if (rc == LUTIL_PASSWD_OK) { 699 AC_MEMCPY(hash->bv_val, hash_otp.bv_val, hash_otp.bv_len); 700 hash->bv_val[hash_otp.bv_len] = DELIM; 701 AC_MEMCPY(hash->bv_val + hash_otp.bv_len + 1, 702 hash_pass.bv_val, hash_pass.bv_len); 703 hash->bv_val[hash->bv_len] = '\0'; 704 } 705 706 /* Cleanup and return */ 707 memset(hash_otp.bv_val, 0, hash_otp.bv_len); 708 memset(hash_pass.bv_val, 0, hash_pass.bv_len); 709 ber_memfree(hash_otp.bv_val); 710 ber_memfree(hash_pass.bv_val); 711 712 return rc; 713 } 714 715 static int hash_totp1( 716 const struct berval *scheme, 717 const struct berval *passwd, 718 struct berval *hash, 719 const char **text) 720 { 721 #if 0 722 if (passwd->bv_len != SHA_DIGEST_LENGTH) { 723 *text = "invalid key length"; 724 return LUTIL_PASSWD_ERR; 725 } 726 #endif 727 return passwd_string32(scheme, passwd, hash); 728 } 729 730 static int hash_totp256( 731 const struct berval *scheme, 732 const struct berval *passwd, 733 struct berval *hash, 734 const char **text) 735 { 736 #if 0 737 if (passwd->bv_len != SHA256_DIGEST_LENGTH) { 738 *text = "invalid key length"; 739 return LUTIL_PASSWD_ERR; 740 } 741 #endif 742 return passwd_string32(scheme, passwd, hash); 743 } 744 745 static int hash_totp512( 746 const struct berval *scheme, 747 const struct berval *passwd, 748 struct berval *hash, 749 const char **text) 750 { 751 #if 0 752 if (passwd->bv_len != SHA512_DIGEST_LENGTH) { 753 *text = "invalid key length"; 754 return LUTIL_PASSWD_ERR; 755 } 756 #endif 757 return passwd_string32(scheme, passwd, hash); 758 } 759 760 static int hash_totp1andpw( 761 const struct berval *scheme, 762 const struct berval *passwd, 763 struct berval *hash, 764 const char **text) 765 { 766 #if 0 767 if (passwd->bv_len != SHA_DIGEST_LENGTH) { 768 *text = "invalid key length"; 769 return LUTIL_PASSWD_ERR; 770 } 771 #endif 772 return hash_totp_and_pw(scheme, passwd, hash, text); 773 } 774 775 static int hash_totp256andpw( 776 const struct berval *scheme, 777 const struct berval *passwd, 778 struct berval *hash, 779 const char **text) 780 { 781 #if 0 782 if (passwd->bv_len != SHA256_DIGEST_LENGTH) { 783 *text = "invalid key length"; 784 return LUTIL_PASSWD_ERR; 785 } 786 #endif 787 return hash_totp_and_pw(scheme, passwd, hash, text); 788 } 789 790 static int hash_totp512andpw( 791 const struct berval *scheme, 792 const struct berval *passwd, 793 struct berval *hash, 794 const char **text) 795 { 796 #if 0 797 if (passwd->bv_len != SHA512_DIGEST_LENGTH) { 798 *text = "invalid key length"; 799 return LUTIL_PASSWD_ERR; 800 } 801 #endif 802 return hash_totp_and_pw(scheme, passwd, hash, text); 803 } 804 805 static int totp_op_cleanup( 806 Operation *op, 807 SlapReply *rs ) 808 { 809 slap_callback *cb; 810 811 /* clear out the current key */ 812 ldap_pvt_thread_pool_setkey( op->o_threadctx, totp_op_cleanup, 813 NULL, 0, NULL, NULL ); 814 815 /* free the callback */ 816 cb = op->o_callback; 817 op->o_callback = cb->sc_next; 818 if (cb->sc_private) 819 ber_bvfree_x(cb->sc_private, op->o_tmpmemctx); 820 op->o_tmpfree( cb, op->o_tmpmemctx ); 821 return 0; 822 } 823 824 static int 825 totp_bind_response( Operation *op, SlapReply *rs ) 826 { 827 Modifications *mod = NULL; 828 BackendInfo *bi = op->o_bd->bd_info; 829 Entry *e; 830 int rc; 831 832 /* we're only interested if the bind was successful */ 833 if ( rs->sr_err != LDAP_SUCCESS ) 834 return SLAP_CB_CONTINUE; 835 836 rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); 837 op->o_bd->bd_info = bi; 838 839 if ( rc != LDAP_SUCCESS ) { 840 return SLAP_CB_CONTINUE; 841 } 842 843 { 844 time_t now; 845 Attribute *a; 846 Modifications *m; 847 char nowstr[ LDAP_LUTIL_GENTIME_BUFSIZE ]; 848 struct berval timestamp; 849 850 /* get the current time */ 851 now = op->o_time; 852 853 /* update the authTimestamp in the user's entry with the current time */ 854 timestamp.bv_val = nowstr; 855 timestamp.bv_len = sizeof(nowstr); 856 slap_timestamp( &now, ×tamp ); 857 858 m = ch_calloc( sizeof(Modifications), 1 ); 859 m->sml_op = LDAP_MOD_REPLACE; 860 m->sml_flags = 0; 861 m->sml_type = ad_authTimestamp->ad_cname; 862 m->sml_desc = ad_authTimestamp; 863 m->sml_numvals = 1; 864 m->sml_values = ch_calloc( sizeof(struct berval), 2 ); 865 m->sml_nvalues = ch_calloc( sizeof(struct berval), 2 ); 866 867 ber_dupbv( &m->sml_values[0], ×tamp ); 868 ber_dupbv( &m->sml_nvalues[0], ×tamp ); 869 m->sml_next = mod; 870 mod = m; 871 872 /* get authTimestamp attribute, if it exists */ 873 if ((a = attr_find( e->e_attrs, ad_authTimestamp)) != NULL && op->o_callback->sc_private) { 874 struct berval *bv = op->o_callback->sc_private; 875 m = ch_calloc( sizeof(Modifications), 1 ); 876 m->sml_op = LDAP_MOD_DELETE; 877 m->sml_flags = 0; 878 m->sml_type = ad_authTimestamp->ad_cname; 879 m->sml_desc = ad_authTimestamp; 880 m->sml_numvals = 1; 881 m->sml_values = ch_calloc( sizeof(struct berval), 2 ); 882 m->sml_nvalues = ch_calloc( sizeof(struct berval), 2 ); 883 884 ber_dupbv( &m->sml_values[0], bv ); 885 ber_dupbv( &m->sml_nvalues[0], bv ); 886 m->sml_next = mod; 887 mod = m; 888 } 889 } 890 891 be_entry_release_r( op, e ); 892 893 /* perform the update */ 894 if ( mod ) { 895 Operation op2 = *op; 896 SlapReply r2 = { REP_RESULT }; 897 slap_callback cb = { NULL, slap_null_cb, NULL, NULL }; 898 899 /* This is a DSA-specific opattr, it never gets replicated. */ 900 op2.o_tag = LDAP_REQ_MODIFY; 901 op2.o_callback = &cb; 902 op2.orm_modlist = mod; 903 op2.o_dn = op->o_bd->be_rootdn; 904 op2.o_ndn = op->o_bd->be_rootndn; 905 op2.o_dont_replicate = 1; 906 rc = op->o_bd->be_modify( &op2, &r2 ); 907 slap_mods_free( mod, 1 ); 908 if (rc != LDAP_SUCCESS) { 909 /* slapd has logged this as a success already, but we 910 * need to fail it because the authTimestamp changed 911 * out from under us. 912 */ 913 rs->sr_err = LDAP_INVALID_CREDENTIALS; 914 connection2anonymous(op->o_conn); 915 op2 = *op; 916 op2.o_callback = NULL; 917 send_ldap_result(&op2, rs); 918 op->o_bd->bd_info = bi; 919 return rs->sr_err; 920 } 921 } 922 923 op->o_bd->bd_info = bi; 924 return SLAP_CB_CONTINUE; 925 } 926 927 static int totp_op_bind( 928 Operation *op, 929 SlapReply *rs ) 930 { 931 /* If this is a simple Bind, stash the Op pointer so our chk 932 * function can find it. Set a cleanup callback to clear it 933 * out when the Bind completes. 934 */ 935 if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE ) { 936 slap_callback *cb; 937 ldap_pvt_thread_pool_setkey( op->o_threadctx, 938 totp_op_cleanup, op, 0, NULL, NULL ); 939 cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx ); 940 cb->sc_response = totp_bind_response; 941 cb->sc_cleanup = totp_op_cleanup; 942 cb->sc_next = op->o_callback; 943 op->o_callback = cb; 944 } 945 return SLAP_CB_CONTINUE; 946 } 947 948 static int totp_db_open( 949 BackendDB *be, 950 ConfigReply *cr 951 ) 952 { 953 int rc = 0; 954 955 if (!ad_authTimestamp) { 956 const char *text = NULL; 957 rc = slap_str2ad("authTimestamp", &ad_authTimestamp, &text); 958 if (rc) { 959 rc = register_at(totp_OpSchema[0].def, totp_OpSchema[0].ad, 0 ); 960 if (rc) { 961 snprintf(cr->msg, sizeof(cr->msg), "unable to find or register authTimestamp attribute: %s (%d)", 962 text, rc); 963 Debug(LDAP_DEBUG_ANY, "totp: %s.\n", cr->msg ); 964 } 965 ad_authTimestamp->ad_type->sat_flags |= SLAP_AT_MANAGEABLE; 966 } 967 } 968 return rc; 969 } 970 971 static slap_overinst totp; 972 973 int 974 totp_initialize(void) 975 { 976 int rc; 977 978 totp.on_bi.bi_type = "totp"; 979 980 totp.on_bi.bi_db_open = totp_db_open; 981 totp.on_bi.bi_op_bind = totp_op_bind; 982 983 rc = lutil_passwd_add((struct berval *) &scheme_totp1, chk_totp1, hash_totp1); 984 if (!rc) 985 rc = lutil_passwd_add((struct berval *) &scheme_totp256, chk_totp256, hash_totp256); 986 if (!rc) 987 rc = lutil_passwd_add((struct berval *) &scheme_totp512, chk_totp512, hash_totp512); 988 if (!rc) 989 rc = lutil_passwd_add((struct berval *) &scheme_totp1andpw, chk_totp1andpw, hash_totp1andpw); 990 if (!rc) 991 rc = lutil_passwd_add((struct berval *) &scheme_totp256andpw, chk_totp256andpw, hash_totp256andpw); 992 if (!rc) 993 rc = lutil_passwd_add((struct berval *) &scheme_totp512andpw, chk_totp512andpw, hash_totp512andpw); 994 if (rc) 995 return rc; 996 997 return overlay_register(&totp); 998 } 999 1000 int init_module(int argc, char *argv[]) { 1001 return totp_initialize(); 1002 } 1003