📄 passwd.c
字号:
} else current_context = 1;/*--------------- VALIDATE IDENTITY ---------------------------------*/ /* make a copy of pass, because sec_login_validate_identity() will clobber the plaintext password passed to it */ passcpy = strdup(pass); password.key.key_type = sec_passwd_plain; password.key.tagged_union.plain = (unsigned char *) passcpy; password.pepper = NULL; password.version_number = sec_passwd_c_version_none; valid = sec_login_validate_identity(login_context, &password, &reset_password, &auth_src, &error_status); /* report unusual error conditions */ if (error_status != error_status_ok && error_status != sec_rgy_passwd_invalid && error_status != sec_login_s_already_valid && error_status != sec_login_s_null_password) { (void) fprintf(stderr, "sec_login_validate_identity failed: %s\n", error_string(error_status)); } /* done with the copy of the password */ (void) free(passcpy); /* Refresh the context if we already have one */ if (current_context) { if (!sec_login_refresh_identity(login_context, &error_status)) { (void) fprintf(stderr, "sec_login_refresh_identity failed: %s\n", error_string(error_status)); } else { passcpy = strdup(pass); password.key.key_type = sec_passwd_plain; password.key.tagged_union.plain = (unsigned char *) passcpy; password.pepper = NULL; password.version_number = sec_passwd_c_version_none; /* Have to validate the refreshed context */ valid = sec_login_validate_identity(login_context, &password, &reset_password, &auth_src, &error_status); /* report unusual error conditions */ if (error_status != error_status_ok && error_status != sec_rgy_passwd_invalid && error_status != sec_login_s_null_password) { (void) fprintf(stderr, "sec_login_validate_identity failed: %s\n", error_string(error_status)); } } /* done with the copy of the password */ (void) free(passcpy); } /* make sure that the authentication service is not an imposter */ if (valid) { if (!sec_login_certify_identity(login_context, &error_status)) { (void) fprintf(stderr, "Authentication service is an imposter!\n"); /* logoutUser(); */ valid = 0; } } pthread_lock_global_np(); return valid;}#endif /* DCE_PASSWD */#ifdef HAVE_KRB4intkrb_check_password(struct passwd *pwd, char *pass){ char realm[REALM_SZ]; char tkfile[KDEMAXPATHLEN]; /* find local realm */ if (krb_get_lrealm(realm, 1) != KSUCCESS) /*(void) strncpy(realm, KRB_REALM, sizeof (realm)); */ (void) strncpy(realm, krb_get_default_realm(), sizeof (realm)); /* Construct a ticket file */ (void) sprintf(tkfile, _PATH_TMP"/xlock_tkt_%d", getpid()); /* Now, let's make the ticket file named above the _active_ tkt file */ krb_set_tkt_string(tkfile); /* ask the kerberos server for a ticket! */ if (krb_get_pw_in_tkt(pwd->pw_name, "", realm, "krbtgt", realm, DEFAULT_TKT_LIFE, pass) == INTK_OK) { unlink(tkfile); return 1; } return 0;}#endif /* HAVE_KERB4 */#ifdef HAVE_KRB5/*- * Pretty much all of this was snatched out of the kinit from the Kerberos5b6 * distribution. The reason why I felt it was necessary to use kinit was * that if someone is locked for a long time, their credentials could expire, * so xlock must be able to get a new ticket. -- dah <rodmur@ecst.csuchico.edu> */#define KRB5_DEFAULT_OPTIONS 0#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */static intkrb_check_password(struct passwd *pwd, char *pass){ krb5_context kcontext; krb5_timestamp now; krb5_ccache ccache = NULL; krb5_principal me; krb5_principal server; int options = KRB5_DEFAULT_OPTIONS; krb5_deltat lifetime = KRB5_DEFAULT_LIFE; krb5_error_code code; krb5_creds my_creds; char *client_name; krb5_address **addrs = (krb5_address **) 0; krb5_preauthtype *preauth = NULL; krb5_data tgtname = { 0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME }; krb5_init_context(&kcontext); krb5_init_ets(kcontext); if ((code = krb5_timeofday(kcontext, &now))) { com_err(ProgramName, code, "while getting time of day"); return 0; /* seems better to deny access, than just exit, which was what happened in kinit */ } if ((code = krb5_cc_default(kcontext, &ccache))) { com_err(ProgramName, code, "while getting default ccache"); return 0; } code = krb5_cc_get_principal(kcontext, ccache, &me); if (code) { if ((code = krb5_parse_name(kcontext, pwd->pw_name, &me))) { com_err(ProgramName, code, "when parsing name %s", pwd->pw_name); return 0; } } if ((code = krb5_unparse_name(kcontext, me, &client_name))) { com_err(ProgramName, code, "when unparsing name"); return 0; } (void) memset((char *) &my_creds, 0, sizeof (my_creds)); my_creds.client = me; if ((code = krb5_build_principal_ext(kcontext, &server, krb5_princ_realm(kcontext, me)->length, krb5_princ_realm(kcontext, me)->data, tgtname.length, tgtname.data, krb5_princ_realm(kcontext, me)->length, krb5_princ_realm(kcontext, me)->data, 0))) { com_err(ProgramName, code, "while building server name"); return 0; } my_creds.server = server; my_creds.times.starttime = 0; my_creds.times.endtime = now + lifetime; my_creds.times.renew_till = 0; if (strlen(pass) == 0) strcpy(pass, "*"); /* if pass is NULL, krb5_get_in_tkt_with_password will prompt with krb5_default_pwd_prompt1 for password, you don't want that in this application, most likely the user won't have '*' for a password -- dah <rodmur@ecst.csuchico.edu> */ code = krb5_get_in_tkt_with_password(kcontext, options, addrs, NULL, preauth, pass, 0, &my_creds, 0); (void) memset(pass, 0, sizeof (pass)); if (code) { if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) return 0; /* bad password entered */ else { com_err(ProgramName, code, "while getting initial credentials"); return 0; } } code = krb5_cc_initialize(kcontext, ccache, me); if (code != 0) { com_err(ProgramName, code, "when initializing cache"); return 0; } code = krb5_cc_store_cred(kcontext, ccache, &my_creds); if (code) { com_err(ProgramName, code, "while storing credentials"); return 0; } krb5_free_principal(kcontext, server); krb5_free_context(kcontext); return 1; /* success */}#endif /* HAVE_KRB5 */#undef passwd#undef pw_name#undef pw_passwd#ifndef SUNOS_ADJUNCT_PASSWD#include <pwd.h>#endif#if ( HAVE_FCNTL_H && defined( USE_MULTIPLE_ROOT ))voidget_multiple(struct passwd *pw){ /* This should be the first element on the linked list. * If not, then there could be problems. * Also all memory allocations tend to force an exit of * the program. This should probably be changed somehow. */ if (pwllh == (pwlptr) NULL) { if ((pwll = new_pwlnode()) == (pwlptr) ENOMEM) { perror("new"); exit(1); } pwllh = pwll; } if ((pwll->pw_name = strdup(pw->pw_name)) == NULL) { perror("new"); exit(1); }#ifdef BSD_AUTH pwll->pw_lc = login_getclass(pw->pw_class);#else if ((pwll->pw_passwd = strdup(pw->pw_passwd)) == NULL) { perror("new"); exit(1); }#endif if ((pwll->next = new_pwlnode()) == (pwlptr) ENOMEM) { perror("new"); exit(1); }}voidset_multiple(void){#ifdef BSD_AUTH struct passwd *pw; pwlptr pwll; if (pwllh == (pwlptr) NULL) { if ((pwll = new_pwlnode()) == (pwlptr) ENOMEM) { perror("new"); exit(1); } pwllh = pwll; } for (pwll = pwllh; pwll->next; pwll = pwll->next); while ((pw = getpwent()) != (struct passwd *) NULL) { if (pw->pw_uid) continue; if ((pwll->pw_name = strdup(pw->pw_name)) == NULL) { perror("new"); exit(1); } pwll->pw_lc = login_getclass(pw->pw_class); if ((pwll->next = new_pwlnode()) == (pwlptr) ENOMEM) { perror("new"); exit(1); } } if (pwll->next = new_pwlnode()) pwll = pwll->next;#else /* !BSD_AUTH */ /* If you thought the above was sick, then you'll think this is * downright horrific. This is set up so that a child process * is created to read in the password entries using getpwent(3C). * In the man pages on the HPs, getpwent(3C) has in it the fact * that once getpwent(3C) has opened the password file, it keeps * it open until the process is finished. Thus, the child * process exits immediately after reading the entire password * file. Otherwise, the password file remains open the entire * time this program is running. * * I went with getpwent(3C) because it will actually read in * the password entries from the NIS maps as well. */ struct passwd *pw; int pipefd[2]; char buf[BUFMAX], xlen; pid_t cid;#ifdef USE_SHADOW struct spwd *spw;#endif if (pipe(pipefd) < 0) { perror("Pipe Generation"); exit(1); } if ((cid = fork()) < 0) { perror("fork"); exit(1); } else if (cid == 0) { /* child process. Used to read in password file. Also checks to * see if the uid is zero. If so, then writes that to the pipe. */ register int sbuf = 0; char *cbuf, *pbuf; close(pipefd[0]); while ((pw = getpwent()) != (struct passwd *) NULL) { if (pw->pw_uid != 0) continue;#ifdef USE_SHADOW if ((spw = getspnam(pw->pw_name)) != NULL) { char *tmp; /* swap */ tmp = pw->pw_passwd; pw->pw_passwd = spw->sp_pwdp; spw->sp_pwdp = tmp; }#endif if (pw->pw_passwd[0] != '*') { xlen = strlen(pw->pw_name); if ((sbuf + xlen) >= BUFMAX) { if (write(pipefd[1], buf, sbuf) != sbuf) perror("write"); sbuf = 0; } cbuf = &buf[sbuf]; *cbuf++ = xlen; for (pbuf = pw->pw_name; *pbuf;) *cbuf++ = *pbuf++; sbuf += xlen + 1; xlen = strlen(pw->pw_passwd); if ((sbuf + xlen) >= BUFMAX) { if (write(pipefd[1], buf, sbuf) != sbuf) perror("write"); sbuf = 0; } cbuf = &buf[sbuf]; *cbuf++ = xlen; for (pbuf = pw->pw_passwd; *pbuf;) *cbuf++ = *pbuf++; sbuf += xlen + 1; } }#ifdef USE_SHADOW endspent();#endif cbuf = &buf[sbuf]; *cbuf = -1; sbuf++; if (write(pipefd[1], buf, sbuf) != sbuf) perror("write"); close(pipefd[1]); exit(0); } else { /* parent process. Does the actual creation of the linked list. * It assumes that everything coming through the pipe are password * entries that are authorized to unlock the screen. */ register int bufsize = BUFMAX, done = 0, sbuf = BUFMAX, i; char *cbuf, *pbuf; pwlptr pwll; close(pipefd[1]); if (pwllh == (pwlptr) NULL) { if ((pwll = new_pwlnode()) == (pwlptr) ENOMEM) { perror("new"); exit(1); } pwllh = pwll; } for (pwll = pwllh; pwll->next; pwll = pwll->next); while (!done) { if (sbuf >= bufsize) { if ((bufsize = read(pipefd[0], buf, BUFMAX)) <= 0) perror("read"); sbuf = 0; } cbuf = &buf[sbuf]; xlen = *cbuf++; if (xlen < 0) { done = 1; break; } sbuf++; if (sbuf >= bufsize) { if ((bufsize = read(pipefd[0], buf, BUFMAX)) <= 0) perror("read"); sbuf = 0; } if ((pwll->pw_name = (char *) malloc(xlen + 1)) == NULL) break; pbuf = pwll->pw_name; cbuf = &buf[sbuf]; for (i = 0; i < xlen; i++) { *pbuf++ = *cbuf++; sbuf++; if (sbuf >= bufsize) { if ((bufsize = read(pipefd[0], buf, BUFMAX)) <= 0) perror("read"); sbuf = 0; cbuf = buf; } } *pbuf = (char) NULL; cbuf = &buf[sbuf]; xlen = *cbuf++; sbuf++; if (sbuf >= bufsize) { if ((bufsize = read(pipefd[0], buf, BUFMAX)) <= 0) perror("read"); sbuf = 0; } if ((pwll->pw_passwd = (char *) malloc(xlen + 1)) == NULL) break; pbuf = pwll->pw_passwd; cbuf = &buf[sbuf]; for (i = 0; i < xlen; i++) { *pbuf++ = *cbuf++; sbuf++; if (sbuf >= bufsize) { if ((bufsize = read(pipefd[0], buf, BUFMAX)) <= 0) perror("read"); sbuf = 0; cbuf = buf; } } *pbuf = (char) NULL; if ((pwll->next = new_pwlnode()) == (pwlptr) ENOMEM) break; pwll = pwll->next; } close(pipefd[0]); }#endif /* !BSD_AUTH */}#endifvoidinitPasswd(void){ getUserName();#if !defined( ultrix ) && !defined( DCE_PASSWD ) && !defined( USE_PAM) if ( mode != MODE_PREVIEW ) {#ifdef BSD_AUTH struct passwd *pwd = getpwnam(user); lc = login_getclass(pwd->pw_class); if (allowroot && (pwd = getpwnam(ROOT)) != NULL) rlc = login_getclass(pwd->pw_class);#else /* !BSD_AUTH */ getCryptedUserPasswd(); if (allowroot) getCryptedRootPasswd();#endif /* !BSD_AUTH */ }#endif /* !ultrix && !DCE_PASSWD && !USE_PAM*/#ifdef DCE_PASSWD initDCE();#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -