1/* 2 Unix SMB/CIFS implementation. 3 Password and authentication handling 4 Copyright (C) Andrew Bartlett 2001 5 Copyright (C) Jeremy Allison 2001 6 Copyright (C) Simo Sorce 2005 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "auth/auth.h" 24#include "auth/ntlm/auth_proto.h" 25#include "system/passwd.h" /* needed by some systems for struct passwd */ 26#include "lib/socket/socket.h" 27#include "auth/ntlm/pam_errors.h" 28#include "param/param.h" 29 30/* TODO: look at how to best fill in parms retrieveing a struct passwd info 31 * except in case USER_INFO_DONT_CHECK_UNIX_ACCOUNT is set 32 */ 33static NTSTATUS authunix_make_server_info(TALLOC_CTX *mem_ctx, 34 const char *netbios_name, 35 const struct auth_usersupplied_info *user_info, 36 struct passwd *pwd, 37 struct auth_serversupplied_info **_server_info) 38{ 39 struct auth_serversupplied_info *server_info; 40 NTSTATUS status; 41 42 /* This is a real, real hack */ 43 if (pwd->pw_uid == 0) { 44 status = auth_system_server_info(mem_ctx, netbios_name, &server_info); 45 if (!NT_STATUS_IS_OK(status)) { 46 return status; 47 } 48 49 server_info->account_name = talloc_steal(server_info, pwd->pw_name); 50 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name); 51 52 server_info->domain_name = talloc_strdup(server_info, "unix"); 53 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name); 54 } else { 55 server_info = talloc(mem_ctx, struct auth_serversupplied_info); 56 NT_STATUS_HAVE_NO_MEMORY(server_info); 57 58 server_info->authenticated = true; 59 60 server_info->account_name = talloc_steal(server_info, pwd->pw_name); 61 NT_STATUS_HAVE_NO_MEMORY(server_info->account_name); 62 63 server_info->domain_name = talloc_strdup(server_info, "unix"); 64 NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name); 65 66 /* This isn't in any way correct.. */ 67 server_info->account_sid = NULL; 68 server_info->primary_group_sid = NULL; 69 server_info->n_domain_groups = 0; 70 server_info->domain_groups = NULL; 71 } 72 server_info->user_session_key = data_blob(NULL,0); 73 server_info->lm_session_key = data_blob(NULL,0); 74 75 server_info->full_name = talloc_steal(server_info, pwd->pw_gecos); 76 NT_STATUS_HAVE_NO_MEMORY(server_info->full_name); 77 server_info->logon_script = talloc_strdup(server_info, ""); 78 NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script); 79 server_info->profile_path = talloc_strdup(server_info, ""); 80 NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path); 81 server_info->home_directory = talloc_strdup(server_info, ""); 82 NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory); 83 server_info->home_drive = talloc_strdup(server_info, ""); 84 NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive); 85 86 server_info->last_logon = 0; 87 server_info->last_logoff = 0; 88 server_info->acct_expiry = 0; 89 server_info->last_password_change = 0; 90 server_info->allow_password_change = 0; 91 server_info->force_password_change = 0; 92 server_info->logon_count = 0; 93 server_info->bad_password_count = 0; 94 server_info->acct_flags = 0; 95 96 *_server_info = server_info; 97 98 return NT_STATUS_OK; 99} 100 101static NTSTATUS talloc_getpwnam(TALLOC_CTX *ctx, const char *username, struct passwd **pws) 102{ 103 struct passwd *ret; 104 struct passwd *from; 105 106 *pws = NULL; 107 108 ret = talloc(ctx, struct passwd); 109 NT_STATUS_HAVE_NO_MEMORY(ret); 110 111 from = getpwnam(username); 112 if (!from) { 113 return NT_STATUS_NO_SUCH_USER; 114 } 115 116 ret->pw_name = talloc_strdup(ctx, from->pw_name); 117 NT_STATUS_HAVE_NO_MEMORY(ret->pw_name); 118 119 ret->pw_passwd = talloc_strdup(ctx, from->pw_passwd); 120 NT_STATUS_HAVE_NO_MEMORY(ret->pw_passwd); 121 122 ret->pw_uid = from->pw_uid; 123 ret->pw_gid = from->pw_gid; 124 ret->pw_gecos = talloc_strdup(ctx, from->pw_gecos); 125 NT_STATUS_HAVE_NO_MEMORY(ret->pw_gecos); 126 127 ret->pw_dir = talloc_strdup(ctx, from->pw_dir); 128 NT_STATUS_HAVE_NO_MEMORY(ret->pw_dir); 129 130 ret->pw_shell = talloc_strdup(ctx, from->pw_shell); 131 NT_STATUS_HAVE_NO_MEMORY(ret->pw_shell); 132 133 *pws = ret; 134 135 return NT_STATUS_OK; 136} 137 138 139#ifdef HAVE_SECURITY_PAM_APPL_H 140#include <security/pam_appl.h> 141 142struct smb_pam_user_info { 143 const char *account_name; 144 const char *plaintext_password; 145}; 146 147#define COPY_STRING(s) (s) ? strdup(s) : NULL 148 149/* 150 * Check user password 151 * Currently it uses PAM only and fails on systems without PAM 152 * Samba3 code located in pass_check.c is to ugly to be used directly it will 153 * need major rework that's why pass_check.c is still there. 154*/ 155 156static int smb_pam_conv(int num_msg, const struct pam_message **msg, 157 struct pam_response **reply, void *appdata_ptr) 158{ 159 struct smb_pam_user_info *info = (struct smb_pam_user_info *)appdata_ptr; 160 int num; 161 162 if (num_msg <= 0) { 163 *reply = NULL; 164 return PAM_CONV_ERR; 165 } 166 167 /* 168 * Apparantly HPUX has a buggy PAM that doesn't support the 169 * data pointer. Fail if this is the case. JRA. 170 */ 171 172 if (info == NULL) { 173 *reply = NULL; 174 return PAM_CONV_ERR; 175 } 176 177 /* 178 * PAM frees memory in reply messages by itself 179 * so use malloc instead of talloc here. 180 */ 181 *reply = malloc_array_p(struct pam_response, num_msg); 182 if (*reply == NULL) { 183 return PAM_CONV_ERR; 184 } 185 186 for (num = 0; num < num_msg; num++) { 187 switch (msg[num]->msg_style) { 188 case PAM_PROMPT_ECHO_ON: 189 (*reply)[num].resp_retcode = PAM_SUCCESS; 190 (*reply)[num].resp = COPY_STRING(info->account_name); 191 break; 192 193 case PAM_PROMPT_ECHO_OFF: 194 (*reply)[num].resp_retcode = PAM_SUCCESS; 195 (*reply)[num].resp = COPY_STRING(info->plaintext_password); 196 break; 197 198 case PAM_TEXT_INFO: 199 (*reply)[num].resp_retcode = PAM_SUCCESS; 200 (*reply)[num].resp = NULL; 201 DEBUG(4,("PAM Info message in conversation function: %s\n", (msg[num]->msg))); 202 break; 203 204 case PAM_ERROR_MSG: 205 (*reply)[num].resp_retcode = PAM_SUCCESS; 206 (*reply)[num].resp = NULL; 207 DEBUG(4,("PAM Error message in conversation function: %s\n", (msg[num]->msg))); 208 break; 209 210 default: 211 while (num > 0) { 212 SAFE_FREE((*reply)[num-1].resp); 213 num--; 214 } 215 SAFE_FREE(*reply); 216 *reply = NULL; 217 DEBUG(1,("Error: PAM subsystme sent an UNKNOWN message type to the conversation function!\n")); 218 return PAM_CONV_ERR; 219 } 220 } 221 222 return PAM_SUCCESS; 223} 224 225/* 226 * Start PAM authentication for specified account 227 */ 228 229static NTSTATUS smb_pam_start(pam_handle_t **pamh, const char *account_name, const char *remote_host, struct pam_conv *pconv) 230{ 231 int pam_error; 232 233 if (account_name == NULL || remote_host == NULL) { 234 return NT_STATUS_INVALID_PARAMETER; 235 } 236 237 DEBUG(4,("smb_pam_start: PAM: Init user: %s\n", account_name)); 238 239 pam_error = pam_start("samba", account_name, pconv, pamh); 240 if (pam_error != PAM_SUCCESS) { 241 /* no valid pamh here, can we reliably call pam_strerror ? */ 242 DEBUG(4,("smb_pam_start: pam_start failed!\n")); 243 return NT_STATUS_UNSUCCESSFUL; 244 } 245 246#ifdef PAM_RHOST 247 DEBUG(4,("smb_pam_start: PAM: setting rhost to: %s\n", remote_host)); 248 pam_error = pam_set_item(*pamh, PAM_RHOST, remote_host); 249 if (pam_error != PAM_SUCCESS) { 250 NTSTATUS nt_status; 251 252 DEBUG(4,("smb_pam_start: setting rhost failed with error: %s\n", 253 pam_strerror(*pamh, pam_error))); 254 nt_status = pam_to_nt_status(pam_error); 255 256 pam_error = pam_end(*pamh, 0); 257 if (pam_error != PAM_SUCCESS) { 258 /* no vaild pamh here, can we reliably call pam_strerror ? */ 259 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n", 260 pam_error)); 261 return pam_to_nt_status(pam_error); 262 } 263 return nt_status; 264 } 265#endif 266#ifdef PAM_TTY 267 DEBUG(4,("smb_pam_start: PAM: setting tty\n")); 268 pam_error = pam_set_item(*pamh, PAM_TTY, "samba"); 269 if (pam_error != PAM_SUCCESS) { 270 NTSTATUS nt_status; 271 272 DEBUG(4,("smb_pam_start: setting tty failed with error: %s\n", 273 pam_strerror(*pamh, pam_error))); 274 nt_status = pam_to_nt_status(pam_error); 275 276 pam_error = pam_end(*pamh, 0); 277 if (pam_error != PAM_SUCCESS) { 278 /* no vaild pamh here, can we reliably call pam_strerror ? */ 279 DEBUG(4,("smb_pam_start: clean up failed, pam_end gave error %d.\n", 280 pam_error)); 281 return pam_to_nt_status(pam_error); 282 } 283 return nt_status; 284 } 285#endif 286 DEBUG(4,("smb_pam_start: PAM: Init passed for user: %s\n", account_name)); 287 288 return NT_STATUS_OK; 289} 290 291static NTSTATUS smb_pam_end(pam_handle_t *pamh) 292{ 293 int pam_error; 294 295 if (pamh != NULL) { 296 pam_error = pam_end(pamh, 0); 297 if (pam_error != PAM_SUCCESS) { 298 /* no vaild pamh here, can we reliably call pam_strerror ? */ 299 DEBUG(4,("smb_pam_end: clean up failed, pam_end gave error %d.\n", 300 pam_error)); 301 return pam_to_nt_status(pam_error); 302 } 303 return NT_STATUS_OK; 304 } 305 306 DEBUG(2,("smb_pam_end: pamh is NULL, PAM not initialized ?\n")); 307 return NT_STATUS_UNSUCCESSFUL; 308} 309 310/* 311 * PAM Authentication Handler 312 */ 313static NTSTATUS smb_pam_auth(pam_handle_t *pamh, bool allow_null_passwords, const char *user) 314{ 315 int pam_error; 316 317 /* 318 * To enable debugging set in /etc/pam.d/samba: 319 * auth required /lib/security/pam_pwdb.so nullok shadow audit 320 */ 321 322 DEBUG(4,("smb_pam_auth: PAM: Authenticate User: %s\n", user)); 323 324 pam_error = pam_authenticate(pamh, PAM_SILENT | allow_null_passwords ? 0 : PAM_DISALLOW_NULL_AUTHTOK); 325 switch( pam_error ){ 326 case PAM_AUTH_ERR: 327 DEBUG(2, ("smb_pam_auth: PAM: Authentication Error for user %s\n", user)); 328 break; 329 case PAM_CRED_INSUFFICIENT: 330 DEBUG(2, ("smb_pam_auth: PAM: Insufficient Credentials for user %s\n", user)); 331 break; 332 case PAM_AUTHINFO_UNAVAIL: 333 DEBUG(2, ("smb_pam_auth: PAM: Authentication Information Unavailable for user %s\n", user)); 334 break; 335 case PAM_USER_UNKNOWN: 336 DEBUG(2, ("smb_pam_auth: PAM: Username %s NOT known to Authentication system\n", user)); 337 break; 338 case PAM_MAXTRIES: 339 DEBUG(2, ("smb_pam_auth: PAM: One or more authentication modules reports user limit for user %s exceeeded\n", user)); 340 break; 341 case PAM_ABORT: 342 DEBUG(0, ("smb_pam_auth: PAM: One or more PAM modules failed to load for user %s\n", user)); 343 break; 344 case PAM_SUCCESS: 345 DEBUG(4, ("smb_pam_auth: PAM: User %s Authenticated OK\n", user)); 346 break; 347 default: 348 DEBUG(0, ("smb_pam_auth: PAM: UNKNOWN ERROR while authenticating user %s\n", user)); 349 break; 350 } 351 352 return pam_to_nt_status(pam_error); 353} 354 355/* 356 * PAM Account Handler 357 */ 358static NTSTATUS smb_pam_account(pam_handle_t *pamh, const char * user) 359{ 360 int pam_error; 361 362 DEBUG(4,("smb_pam_account: PAM: Account Management for User: %s\n", user)); 363 364 pam_error = pam_acct_mgmt(pamh, PAM_SILENT); /* Is user account enabled? */ 365 switch( pam_error ) { 366 case PAM_AUTHTOK_EXPIRED: 367 DEBUG(2, ("smb_pam_account: PAM: User %s is valid but password is expired\n", user)); 368 break; 369 case PAM_ACCT_EXPIRED: 370 DEBUG(2, ("smb_pam_account: PAM: User %s no longer permitted to access system\n", user)); 371 break; 372 case PAM_AUTH_ERR: 373 DEBUG(2, ("smb_pam_account: PAM: There was an authentication error for user %s\n", user)); 374 break; 375 case PAM_PERM_DENIED: 376 DEBUG(0, ("smb_pam_account: PAM: User %s is NOT permitted to access system at this time\n", user)); 377 break; 378 case PAM_USER_UNKNOWN: 379 DEBUG(0, ("smb_pam_account: PAM: User \"%s\" is NOT known to account management\n", user)); 380 break; 381 case PAM_SUCCESS: 382 DEBUG(4, ("smb_pam_account: PAM: Account OK for User: %s\n", user)); 383 break; 384 default: 385 DEBUG(0, ("smb_pam_account: PAM: UNKNOWN PAM ERROR (%d) during Account Management for User: %s\n", pam_error, user)); 386 break; 387 } 388 389 return pam_to_nt_status(pam_error); 390} 391 392/* 393 * PAM Credential Setting 394 */ 395 396static NTSTATUS smb_pam_setcred(pam_handle_t *pamh, const char * user) 397{ 398 int pam_error; 399 400 /* 401 * This will allow samba to aquire a kerberos token. And, when 402 * exporting an AFS cell, be able to /write/ to this cell. 403 */ 404 405 DEBUG(4,("PAM: Account Management SetCredentials for User: %s\n", user)); 406 407 pam_error = pam_setcred(pamh, (PAM_ESTABLISH_CRED|PAM_SILENT)); 408 switch( pam_error ) { 409 case PAM_CRED_UNAVAIL: 410 DEBUG(0, ("smb_pam_setcred: PAM: Credentials not found for user:%s\n", user )); 411 break; 412 case PAM_CRED_EXPIRED: 413 DEBUG(0, ("smb_pam_setcred: PAM: Credentials for user: \"%s\" EXPIRED!\n", user )); 414 break; 415 case PAM_USER_UNKNOWN: 416 DEBUG(0, ("smb_pam_setcred: PAM: User: \"%s\" is NOT known so can not set credentials!\n", user )); 417 break; 418 case PAM_CRED_ERR: 419 DEBUG(0, ("smb_pam_setcred: PAM: Unknown setcredentials error - unable to set credentials for %s\n", user )); 420 break; 421 case PAM_SUCCESS: 422 DEBUG(4, ("smb_pam_setcred: PAM: SetCredentials OK for User: %s\n", user)); 423 break; 424 default: 425 DEBUG(0, ("smb_pam_setcred: PAM: UNKNOWN PAM ERROR (%d) during SetCredentials for User: %s\n", pam_error, user)); 426 break; 427 } 428 429 return pam_to_nt_status(pam_error); 430} 431 432static NTSTATUS check_unix_password(TALLOC_CTX *ctx, struct loadparm_context *lp_ctx, 433 const struct auth_usersupplied_info *user_info, struct passwd **pws) 434{ 435 struct smb_pam_user_info *info; 436 struct pam_conv *pamconv; 437 pam_handle_t *pamh; 438 NTSTATUS nt_status; 439 440 info = talloc(ctx, struct smb_pam_user_info); 441 if (info == NULL) { 442 return NT_STATUS_NO_MEMORY; 443 } 444 445 info->account_name = user_info->mapped.account_name; 446 info->plaintext_password = user_info->password.plaintext; 447 448 pamconv = talloc(ctx, struct pam_conv); 449 if (pamconv == NULL) { 450 return NT_STATUS_NO_MEMORY; 451 } 452 453 pamconv->conv = smb_pam_conv; 454 pamconv->appdata_ptr = (void *)info; 455 456 /* TODO: 457 * check for user_info->flags & USER_INFO_CASE_INSENSITIVE_USERNAME 458 * if true set up a crack name routine. 459 */ 460 461 nt_status = smb_pam_start(&pamh, user_info->mapped.account_name, user_info->remote_host ? user_info->remote_host->addr : NULL, pamconv); 462 if (!NT_STATUS_IS_OK(nt_status)) { 463 return nt_status; 464 } 465 466 nt_status = smb_pam_auth(pamh, lp_null_passwords(lp_ctx), user_info->mapped.account_name); 467 if (!NT_STATUS_IS_OK(nt_status)) { 468 smb_pam_end(pamh); 469 return nt_status; 470 } 471 472 if ( ! (user_info->flags & USER_INFO_DONT_CHECK_UNIX_ACCOUNT)) { 473 474 nt_status = smb_pam_account(pamh, user_info->mapped.account_name); 475 if (!NT_STATUS_IS_OK(nt_status)) { 476 smb_pam_end(pamh); 477 return nt_status; 478 } 479 480 nt_status = smb_pam_setcred(pamh, user_info->mapped.account_name); 481 if (!NT_STATUS_IS_OK(nt_status)) { 482 smb_pam_end(pamh); 483 return nt_status; 484 } 485 } 486 487 smb_pam_end(pamh); 488 489 nt_status = talloc_getpwnam(ctx, user_info->mapped.account_name, pws); 490 if (!NT_STATUS_IS_OK(nt_status)) { 491 return nt_status; 492 } 493 494 return NT_STATUS_OK; 495} 496 497#else 498 499/**************************************************************************** 500core of password checking routine 501****************************************************************************/ 502static NTSTATUS password_check(const char *username, const char *password, 503 const char *crypted, const char *salt) 504{ 505 bool ret; 506 507#ifdef WITH_AFS 508 if (afs_auth(username, password)) 509 return NT_STATUS_OK; 510#endif /* WITH_AFS */ 511 512#ifdef WITH_DFS 513 if (dfs_auth(username, password)) 514 return NT_STATUS_OK; 515#endif /* WITH_DFS */ 516 517#ifdef OSF1_ENH_SEC 518 519 ret = (strcmp(osf1_bigcrypt(password, salt), crypted) == 0); 520 521 if (!ret) { 522 DEBUG(2, 523 ("OSF1_ENH_SEC failed. Trying normal crypt.\n")); 524 ret = (strcmp((char *)crypt(password, salt), crypted) == 0); 525 } 526 if (ret) { 527 return NT_STATUS_OK; 528 } else { 529 return NT_STATUS_WRONG_PASSWORD; 530 } 531 532#endif /* OSF1_ENH_SEC */ 533 534#ifdef ULTRIX_AUTH 535 ret = (strcmp((char *)crypt16(password, salt), crypted) == 0); 536 if (ret) { 537 return NT_STATUS_OK; 538 } else { 539 return NT_STATUS_WRONG_PASSWORD; 540 } 541 542#endif /* ULTRIX_AUTH */ 543 544#ifdef LINUX_BIGCRYPT 545 ret = (linux_bigcrypt(password, salt, crypted)); 546 if (ret) { 547 return NT_STATUS_OK; 548 } else { 549 return NT_STATUS_WRONG_PASSWORD; 550 } 551#endif /* LINUX_BIGCRYPT */ 552 553#if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS) 554 555 /* 556 * Some systems have bigcrypt in the C library but might not 557 * actually use it for the password hashes (HPUX 10.20) is 558 * a noteable example. So we try bigcrypt first, followed 559 * by crypt. 560 */ 561 562 if (strcmp(bigcrypt(password, salt), crypted) == 0) 563 return NT_STATUS_OK; 564 else 565 ret = (strcmp((char *)crypt(password, salt), crypted) == 0); 566 if (ret) { 567 return NT_STATUS_OK; 568 } else { 569 return NT_STATUS_WRONG_PASSWORD; 570 } 571#else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */ 572 573#ifdef HAVE_BIGCRYPT 574 ret = (strcmp(bigcrypt(password, salt), crypted) == 0); 575 if (ret) { 576 return NT_STATUS_OK; 577 } else { 578 return NT_STATUS_WRONG_PASSWORD; 579 } 580#endif /* HAVE_BIGCRYPT */ 581 582#ifndef HAVE_CRYPT 583 DEBUG(1, ("Warning - no crypt available\n")); 584 return NT_STATUS_LOGON_FAILURE; 585#else /* HAVE_CRYPT */ 586 ret = (strcmp((char *)crypt(password, salt), crypted) == 0); 587 if (ret) { 588 return NT_STATUS_OK; 589 } else { 590 return NT_STATUS_WRONG_PASSWORD; 591 } 592#endif /* HAVE_CRYPT */ 593#endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */ 594} 595 596static NTSTATUS check_unix_password(TALLOC_CTX *ctx, struct loadparm_context *lp_ctx, 597 const struct auth_usersupplied_info *user_info, struct passwd **ret_passwd) 598{ 599 char *username; 600 char *password; 601 char *pwcopy; 602 char *salt; 603 char *crypted; 604 struct passwd *pws; 605 NTSTATUS nt_status; 606 int level = lp_passwordlevel(lp_ctx); 607 608 *ret_passwd = NULL; 609 610 username = talloc_strdup(ctx, user_info->mapped.account_name); 611 password = talloc_strdup(ctx, user_info->password.plaintext); 612 613 nt_status = talloc_getpwnam(ctx, username, &pws); 614 if (!NT_STATUS_IS_OK(nt_status)) { 615 return nt_status; 616 } 617 618 crypted = pws->pw_passwd; 619 salt = pws->pw_passwd; 620 621#ifdef HAVE_GETSPNAM 622 { 623 struct spwd *spass; 624 625 /* many shadow systems require you to be root to get 626 the password, in most cases this should already be 627 the case when this function is called, except 628 perhaps for IPC password changing requests */ 629 630 spass = getspnam(pws->pw_name); 631 if (spass && spass->sp_pwdp) { 632 crypted = talloc_strdup(ctx, spass->sp_pwdp); 633 NT_STATUS_HAVE_NO_MEMORY(crypted); 634 salt = talloc_strdup(ctx, spass->sp_pwdp); 635 NT_STATUS_HAVE_NO_MEMORY(salt); 636 } 637 } 638#elif defined(IA_UINFO) 639 { 640 char *ia_password; 641 /* Need to get password with SVR4.2's ia_ functions 642 instead of get{sp,pw}ent functions. Required by 643 UnixWare 2.x, tested on version 644 2.1. (tangent@cyberport.com) */ 645 uinfo_t uinfo; 646 if (ia_openinfo(pws->pw_name, &uinfo) != -1) { 647 ia_get_logpwd(uinfo, &ia_password); 648 crypted = talloc_strdup(ctx, ia_password); 649 NT_STATUS_HAVE_NO_MEMORY(crypted); 650 } 651 } 652#endif 653 654#ifdef HAVE_GETPRPWNAM 655 { 656 struct pr_passwd *pr_pw = getprpwnam(pws->pw_name); 657 if (pr_pw && pr_pw->ufld.fd_encrypt) { 658 crypted = talloc_strdup(ctx, pr_pw->ufld.fd_encrypt); 659 NT_STATUS_HAVE_NO_MEMORY(crypted); 660 } 661 } 662#endif 663 664#ifdef HAVE_GETPWANAM 665 { 666 struct passwd_adjunct *pwret; 667 pwret = getpwanam(s); 668 if (pwret && pwret->pwa_passwd) { 669 crypted = talloc_strdup(ctx, pwret->pwa_passwd); 670 NT_STATUS_HAVE_NO_MEMORY(crypted); 671 } 672 } 673#endif 674 675#ifdef OSF1_ENH_SEC 676 { 677 struct pr_passwd *mypasswd; 678 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n", username)); 679 mypasswd = getprpwnam(username); 680 if (mypasswd) { 681 username = talloc_strdup(ctx, mypasswd->ufld.fd_name); 682 NT_STATUS_HAVE_NO_MEMORY(username); 683 crypted = talloc_strdup(ctx, mypasswd->ufld.fd_encrypt); 684 NT_STATUS_HAVE_NO_MEMORY(crypted); 685 } else { 686 DEBUG(5,("OSF1_ENH_SEC: No entry for user %s in protected database !\n", username)); 687 } 688 } 689#endif 690 691#ifdef ULTRIX_AUTH 692 { 693 AUTHORIZATION *ap = getauthuid(pws->pw_uid); 694 if (ap) { 695 crypted = talloc_strdup(ctx, ap->a_password); 696 endauthent(); 697 NT_STATUS_HAVE_NO_MEMORY(crypted); 698 } 699 } 700#endif 701 702#if defined(HAVE_TRUNCATED_SALT) 703 /* crypt on some platforms (HPUX in particular) 704 won't work with more than 2 salt characters. */ 705 salt[2] = 0; 706#endif 707 708 if (crypted[0] == '\0') { 709 if (!lp_null_passwords(lp_ctx)) { 710 DEBUG(2, ("Disallowing %s with null password\n", username)); 711 return NT_STATUS_LOGON_FAILURE; 712 } 713 if (password == NULL) { 714 DEBUG(3, ("Allowing access to %s with null password\n", username)); 715 *ret_passwd = pws; 716 return NT_STATUS_OK; 717 } 718 } 719 720 /* try it as it came to us */ 721 nt_status = password_check(username, password, crypted, salt); 722 if (NT_STATUS_IS_OK(nt_status)) { 723 *ret_passwd = pws; 724 return nt_status; 725 } 726 else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) { 727 /* No point continuing if its not the password thats to blame (ie PAM disabled). */ 728 return nt_status; 729 } 730 731 if ( user_info->flags | USER_INFO_CASE_INSENSITIVE_PASSWORD) { 732 return nt_status; 733 } 734 735 /* if the password was given to us with mixed case then we don't 736 * need to proceed as we know it hasn't been case modified by the 737 * client */ 738 if (strhasupper(password) && strhaslower(password)) { 739 return nt_status; 740 } 741 742 /* make a copy of it */ 743 pwcopy = talloc_strdup(ctx, password); 744 if (!pwcopy) 745 return NT_STATUS_NO_MEMORY; 746 747 /* try all lowercase if it's currently all uppercase */ 748 if (strhasupper(pwcopy)) { 749 strlower(pwcopy); 750 nt_status = password_check(username, pwcopy, crypted, salt); 751 if NT_STATUS_IS_OK(nt_status) { 752 *ret_passwd = pws; 753 return nt_status; 754 } 755 } 756 757 /* give up? */ 758 if (level < 1) { 759 return NT_STATUS_WRONG_PASSWORD; 760 } 761 762 /* last chance - all combinations of up to level chars upper! */ 763 strlower(pwcopy); 764 765#if 0 766 if (NT_STATUS_IS_OK(nt_status = string_combinations(pwcopy, password_check, level))) { 767 *ret_passwd = pws; 768 return nt_status; 769 } 770#endif 771 return NT_STATUS_WRONG_PASSWORD; 772} 773 774#endif 775 776/** Check a plaintext username/password 777 * 778 **/ 779 780static NTSTATUS authunix_want_check(struct auth_method_context *ctx, 781 TALLOC_CTX *mem_ctx, 782 const struct auth_usersupplied_info *user_info) 783{ 784 if (!user_info->mapped.account_name || !*user_info->mapped.account_name) { 785 return NT_STATUS_NOT_IMPLEMENTED; 786 } 787 788 return NT_STATUS_OK; 789} 790 791static NTSTATUS authunix_check_password(struct auth_method_context *ctx, 792 TALLOC_CTX *mem_ctx, 793 const struct auth_usersupplied_info *user_info, 794 struct auth_serversupplied_info **server_info) 795{ 796 TALLOC_CTX *check_ctx; 797 NTSTATUS nt_status; 798 struct passwd *pwd; 799 800 if (user_info->password_state != AUTH_PASSWORD_PLAIN) { 801 return NT_STATUS_INVALID_PARAMETER; 802 } 803 804 check_ctx = talloc_named_const(mem_ctx, 0, "check_unix_password"); 805 if (check_ctx == NULL) { 806 return NT_STATUS_NO_MEMORY; 807 } 808 809 nt_status = check_unix_password(check_ctx, ctx->auth_ctx->lp_ctx, user_info, &pwd); 810 if (!NT_STATUS_IS_OK(nt_status)) { 811 talloc_free(check_ctx); 812 return nt_status; 813 } 814 815 nt_status = authunix_make_server_info(mem_ctx, lp_netbios_name(ctx->auth_ctx->lp_ctx), 816 user_info, pwd, server_info); 817 if (!NT_STATUS_IS_OK(nt_status)) { 818 talloc_free(check_ctx); 819 return nt_status; 820 } 821 822 talloc_free(check_ctx); 823 return NT_STATUS_OK; 824} 825 826static const struct auth_operations unix_ops = { 827 .name = "unix", 828 .get_challenge = auth_get_challenge_not_implemented, 829 .want_check = authunix_want_check, 830 .check_password = authunix_check_password 831}; 832 833_PUBLIC_ NTSTATUS auth_unix_init(void) 834{ 835 NTSTATUS ret; 836 837 ret = auth_register(&unix_ops); 838 if (!NT_STATUS_IS_OK(ret)) { 839 DEBUG(0,("Failed to register unix auth backend!\n")); 840 return ret; 841 } 842 843 return ret; 844} 845