📄 passwd_nisplus.c
字号:
host2netname (usernetname, hostname, NULL); } else user2netname (usernetname, getuid (), NULL); /* get old password for decrypting secret key and further use. */ memset (oldpwd, '\0', sizeof (oldpwd)); strncpy (oldpwd, data->oldclearpwd, sizeof (oldpwd) -1); if (!getsecretkey (usernetname, skey_data, oldpwd)) { if (!getsecretkey (usernetname, skey_data, getpass ("Enter RPC secure password: "))) { fprintf (stderr, _("Can't find %s's secret key\n"), usernetname); return -1; } } /* fill in request struct */ memset (&request, '\0', sizeof (request)); request.ident = 0; request.key_type = strdup ("DES"); request.domain = strdup (nis_domain_of (obj->zo_domain)); request.username = strndup (NISENTRYVAL(0,obj), NISENTRYLEN(0,obj)); /* get publickey of the user */ memset (pkey_user, '\0', sizeof (pkey_user)); if (getpublickey (usernetname, pkey_user) == 0 || pkey_user[0] == '\0') { fprintf (stderr, _("Could not get public key for %s!\n"), usernetname); return -1; } request.user_pub_key.user_pub_key_len = HEXKEYBYTES; request.user_pub_key.user_pub_key_val = (unsigned char *) pkey_user; /* get publickey of the server running rpc.nispasswdd. For that, we have to find the name of the master server for the user domain. */ server = nis_getservlist (request.domain); if (server[0] == NULL) { fprintf (stderr, _("Could not determine the NIS+ root server!\n")); return -1; } masterhost = strdup (server[0]->name); cp = strchr (masterhost, '.'); *cp = '\0'; nis_freeservlist (server); host2netname (servernetname, masterhost, NULL); memset (pkey_host, '\0', sizeof (pkey_host)); if (getpublickey (servernetname, pkey_host) == 0 || pkey_host[0] == '\0') { fprintf (stderr, _("Could not get public key for %s!\n"), servernetname); return -1; } /* Generate common DES key from public server key and secret user key */ if (key_get_conv (pkey_host, &CK) != 0) { fprintf (stderr, _("Could not create conversion key!\n")); return -1; } /* encrypt old clear password. Don't know why Sun needs 16 byte, normaly a password could only be 8 byte. And later in the protocol SUN allows only 12 byte. */ memset (ivec, 0, 8); error = cbc_crypt ((char *) &CK, oldpwd, 16, DES_ENCRYPT | DES_HW, ivec); if (DES_FAILED (error)) { fprintf (stderr, _("DES encryption failure\n")); return -1; } request.npd_authpass.npd_authpass_len = 16; request.npd_authpass.npd_authpass_val = (unsigned char *) oldpwd; /* Try to authenticate us and the server. XXX This should be done in a loop, since the server could be bussy or the password wrong */ clnt = clnt_create (masterhost, NISPASSWD_PROG, NISPASSWD_VERS, "tcp"); if (clnt == NULL) { fprintf (stderr, _("rpc.nispasswd not running on %s?\n"), masterhost); return -1; } memset ((char *) &result, 0, sizeof (result)); timeout.tv_sec = 25; timeout.tv_usec = 0; error = clnt_call (clnt, NISPASSWD_AUTHENTICATE, (xdrproc_t) __pam_xdr_npd_request, (caddr_t) &request, (xdrproc_t) __pam_xdr_nispasswd_authresult, (caddr_t) &result, timeout); if (error) { clnt_perrno (error); fputs ("\n", stderr); return -1; } if (result.status != NPD_SUCCESS) { if (result.status == NPD_TRYAGAIN) fprintf (stderr, _("ERROR: password incorrect, try again\n")); else fprintf (stderr, _("ERROR: %s\n password not changed\n"), npderr2str (result.nispasswd_authresult_u.npd_err)); return -1; } /* Decrypt the ID and the random value. Not easy, since Sparc's are big endian, i?86 little endian, we have to revert to big endian for decrypt */ memset (&cryptbuf, '\0', sizeof (cryptbuf)); ixdr = &cryptbuf.key.high; IXDR_PUT_U_INT32 (ixdr, result.nispasswd_authresult_u.npd_verf.npd_xid); IXDR_PUT_U_INT32 (ixdr, result.nispasswd_authresult_u.npd_verf.npd_xrandval); error = ecb_crypt ((char *) &CK, (char *) &cryptbuf, 8, DES_DECRYPT | DES_HW); if (DES_FAILED (error)) { fprintf (stderr, _("DES decryption failure!\n")); return -1; } /* fill out update request */ memset (&update, 0, sizeof (update)); update.ident = ntohl (cryptbuf.key.high); update.xnewpass.npd_xrandval = cryptbuf.key.low; memset (update.xnewpass.pass, '\0', __NPD_MAXPASSBYTES); strncpy (update.xnewpass.pass, data->oldclearpwd, __NPD_MAXPASSBYTES); if (data->new_gecos) update.pass_info.pw_gecos = strdup (data->new_gecos); else update.pass_info.pw_gecos = ""; if (data->new_shell) update.pass_info.pw_shell = strdup (data->new_shell); else update.pass_info.pw_shell = ""; memset (ivec, 0, 8); error = cbc_crypt ((char *) &CK, (char *) &update.xnewpass, 16, DES_ENCRYPT | DES_HW, ivec); if (DES_FAILED (error)) { fprintf (stderr, _("DES decryption failure!\n")); return -1; } /* update.xnewpass.npd_xrandval will be changed in XDR again */ update.xnewpass.npd_xrandval = ntohl (update.xnewpass.npd_xrandval); memset ((char *) &updresult, 0, sizeof (updresult)); timeout.tv_sec = 25; timeout.tv_usec = 0; error = clnt_call (clnt, NISPASSWD_UPDATE, (xdrproc_t) __pam_xdr_npd_update, (caddr_t) &update, (xdrproc_t) __pam_xdr_nispasswd_updresult, (caddr_t) &updresult, timeout); if (error) { clnt_perrno (error); fprintf (stderr, "\n"); return -1; } clnt_destroy (clnt); if (updresult.status != NPD_SUCCESS) { if (updresult.status == NPD_FAILED) { fprintf (stderr, _("ERROR: %s\n password not changed\n"), npderr2str (updresult.nispasswd_updresult_u.npd_err)); } else if (updresult.status == NPD_PARTIALSUCCESS) { nispasswd_error *err; fputs ("ERROR: Only partial success\n", stderr); err = &updresult.nispasswd_updresult_u.reason; while (err != NULL) { switch (err->npd_field) { case NPD_PASSWD: fprintf (stderr, "\tpassword field: %s\n", npderr2str (err->npd_code)); break; case NPD_GECOS: fprintf (stderr, "\tgecos field: %s\n", npderr2str (err->npd_code)); case NPD_SHELL: fprintf (stderr, "\tshell field: %s\n", npderr2str (err->npd_code)); break; case NPD_SECRETKEY: fprintf (stderr, "\tsecret key: %s\n", npderr2str (err->npd_code)); break; } err = err->next; } } else { fprintf (stderr, _("ERROR: Unknown error, don't know what happend\n")); } return -1; } fprintf (stderr, _("NIS+ password information changed for %s\n"), request.username); fprintf (stderr, _("NIS+ credential information changed for %s\n"), request.username); nis_free_object (obj); return 0;}/* Update password in NIS+ passwd table, do not use rpc.nispasswdd */static intupdate_nisd (nis_object *obj, user_t *data){ char buf[strlen (obj->zo_name) + strlen (obj->zo_domain) + 10]; nis_result *result; if (data->new_gecos) { free (NISENTRYVAL(4,obj)); NISENTRYVAL(4,obj) = strdup (data->new_gecos); NISENTRYFLAG(4,obj) = NISENTRYFLAG(4,obj) | EN_MODIFIED; NISENTRYLEN(4,obj) = strlen (NISENTRYVAL(4,obj)); } if (data->new_shell) { free (NISENTRYVAL(6,obj)); NISENTRYVAL(6,obj) = strdup (data->new_shell); NISENTRYFLAG(6,obj) = NISENTRYFLAG(6,obj) | EN_MODIFIED; NISENTRYLEN(6,obj) = strlen (NISENTRYVAL(6,obj)); } sprintf (buf, "%s.%s", obj->zo_name, obj->zo_domain); result = nis_modify_entry (buf, obj, 0); if (result->status != NIS_SUCCESS) { fprintf (stderr, "nispasswd: Password information update failed\n"); fprintf (stderr, " %s\n", nis_sperrno (result->status)); nis_freeresult (result); return 1; } else nis_freeresult (result); nis_free_object (obj); return 0;}intnpd_upd_pwd (const char *domainname, user_t *data){ nis_result *result; nis_object *obj; char domain[NIS_MAXNAMELEN + 1]; char *buf = NULL; char *group; if (strlen (domainname) == 0) strncpy (domain, nis_local_directory (), NIS_MAXNAMELEN); else strncpy (domain, domainname, NIS_MAXNAMELEN); domain[NIS_MAXNAMELEN] = '\0'; /* Get group of passwd table */ buf = alloca (strlen (data->pw.pw_name) + strlen (domain) + 30); sprintf (buf, "passwd.org_dir.%s", domain); result = nis_lookup (buf, 0); if (result->status != NIS_SUCCESS) { fprintf (stderr, _("NIS+ passwd table not found: %s\n"), nis_sperrno (result->status)); return -1; } group = alloca (strlen (NIS_RES_OBJECT(result)->zo_group) + 1); strcpy (group, NIS_RES_OBJECT(result)->zo_group); nis_freeresult (result); /* Get old NIS+ passwd information for caller or parameter. */ sprintf (buf, "[name=%s],passwd.org_dir.%s", data->pw.pw_name, domain); result = nis_list (buf, 0, NULL, NULL); if (result->status != NIS_SUCCESS) { fprintf (stderr, _("User not found in NIS+ table.\n")); return -1; } obj = nis_clone_object (result->objects.objects_val, NULL); nis_freeresult (result); if (nis_ismember (nis_local_principal (), group)) return update_nisd (obj, data); else return update_npd (obj, data);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -