/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PK_FILES 1 #define PK_YP 2 #define PK_LDAP 4 #define CURMECH mechs[mcount] #define DESCREDPASSLEN sizeof (des_block) static char CRED_TABLE[] = "cred.org_dir"; static char PKMAP[] = "publickey.byname"; static char PKFILE[] = "/etc/publickey"; #define MAXHOSTNAMELEN 256 #define ROOTKEY_FILE "/etc/.rootkey" #define ROOTKEY_FILE_BACKUP "/etc/.rootkey.bak" #define MAXROOTKEY_LINE_LEN 4224 /* Good upto 16384-bit keys */ #define MAXROOTKEY_LEN 4096 /* Should last up to 16384-bit keys */ #define MAXPKENTLEN 8500 bool_t makenew = TRUE; /* Make new keys or reencrypt existing */ bool_t specmech = FALSE; /* Specific mechs requested */ bool_t force = FALSE; int dest_service = 0; /* To which nameservice do we store key(s) */ char *program_name; mechanism_t **mechs = NULL; /* List of DH mechanisms */ char **plist = NULL; /* List of public key(s) */ char **slist = NULL; /* List of secret key(s) */ char **clist = NULL; /* List of encrypted secret key(s) */ int numspecmech = 0; /* Number of mechanisms specified */ struct passwd *pw = NULL; /* passwd entry of user */ struct spwd *spw = NULL; /* shadow entry of user */ char *netname = NULL; /* RPC netname of user */ char local_domain[MAXNETNAMELEN + 1]; char *sec_domain = NULL; char **rpc_pws = NULL; /* List of S-RPC passwords */ int rpc_pw_count = 0; /* Number of passwords entered by user */ char *login_pw = NULL; /* Unencrypted login password */ char short_login_pw[DESCREDPASSLEN + 1]; /* Short S-RPC password, which has first 8 chars of login_pw */ static int add_cred_obj(nis_object *, char *); static void cmp_passwd(); static void encryptkeys(); static void error_msg(); static char *fgets_ignorenul(); static void getpublics(); static void getrpcpws(); static void getsecrets(); static void initkeylist(bool_t); static void keylogin(keylen_t, algtype_t); static void keylogin_des(); static void makenewkeys(); static int modify_cred_obj(nis_object *, char *); static void storekeys(); static void usage(); static void write_rootkey(); extern nis_object *init_entry(); extern int get_pk_source(char *); extern int localupdate(char *, char *, uint_t, char *); extern int xencrypt(); extern int xencrypt_g(); extern int __gen_dhkeys(); extern int key_setnet(); extern int key_setnet_g(); extern int key_secretkey_is_set_g(); extern int __getnetnamebyuid(); extern int getdomainname(); extern int ldap_update(char *, char *, char *, char *, char *); static void error_msg() { if (sec_domain && *sec_domain && strcasecmp(sec_domain, local_domain)) { fprintf(stderr, "The system default domain '%s' is different from the Secure RPC\n\ domain %s where the key is stored. \n", local_domain, sec_domain); exit(1); } } static void usage() { fprintf(stderr, "usage: %s [-p] [-s ldap | nis | files] \n", program_name); exit(1); } /* Encrypt secret key(s) with login_pw */ static void encryptkeys() { int mcount, ccount = 0; if (mechs) { for (mcount = 0; CURMECH; mcount++) { char *crypt = NULL; if (!xencrypt_g(slist[mcount], CURMECH->keylen, CURMECH->algtype, short_login_pw, netname, &crypt, TRUE)) { /* Could not crypt key */ crypt = NULL; } else ccount++; clist[mcount] = crypt; } } else { char *crypt = NULL; if (!(crypt = (char *)malloc(HEXKEYBYTES + KEYCHECKSUMSIZE + 1))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } (void) memcpy(crypt, slist[0], HEXKEYBYTES); (void) memcpy(crypt + HEXKEYBYTES, slist[0], KEYCHECKSUMSIZE); crypt[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0; xencrypt(crypt, short_login_pw); clist[0] = crypt; ccount++; } if (!ccount) { fprintf(stderr, "%s: Could not encrypt any secret keys.\n", program_name); exit(1); } } /* Initialize the array of public, secret, and encrypted secret keys */ static void initkeylist(bool_t nomech) { int mcount; if (!nomech) { assert(mechs && mechs[0]); for (mcount = 0; CURMECH; mcount++) ; } else mcount = 1; if (!(plist = (char **)malloc(sizeof (char *) * mcount))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } if (!(slist = (char **)malloc(sizeof (char *) * mcount))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } if (!(clist = (char **)malloc(sizeof (char *) * mcount))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } } /* Retrieve public key(s) */ static void getpublics() { int mcount; int pcount = 0; if (mechs) { for (mcount = 0; CURMECH; mcount++) { char *public; size_t hexkeylen; hexkeylen = ((CURMECH->keylen / 8) * 2) + 1; if (!(public = (char *)malloc(hexkeylen))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } if (!getpublickey_g(netname, CURMECH->keylen, CURMECH->algtype, public, hexkeylen)) { /* Could not get public key */ fprintf(stderr, "Could not get %s public key.\n", VALID_ALIAS(CURMECH->alias) ? CURMECH->alias : ""); free(public); public = NULL; } else pcount++; plist[mcount] = public; } } else { char *public; if (!(public = (char *)malloc(HEXKEYBYTES + 1))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } if (!getpublickey(netname, public)) { free(public); public = NULL; } else pcount++; plist[0] = public; } if (!pcount) { fprintf(stderr, "%s: cannot get any public keys for %s.\n", program_name, pw->pw_name); error_msg(); fprintf(stderr, "Make sure that the public keys are stored in the domain %s.\n", local_domain); exit(1); } } /* Generate a new set of public/secret key pair(s) */ static void makenewkeys() { int mcount; if (mechs) { for (mcount = 0; CURMECH; mcount++) { char *public, *secret; size_t hexkeylen; if (slist[mcount]) free(slist[mcount]); hexkeylen = ((CURMECH->keylen / 8) * 2) + 1; if (!(public = malloc(hexkeylen))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } if (!(secret = malloc(hexkeylen))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } if (!(__gen_dhkeys_g(public, secret, CURMECH->keylen, CURMECH->algtype, short_login_pw))) { /* Could not generate key pair */ fprintf(stderr, "WARNING Could not generate key pair %s\n", VALID_ALIAS(CURMECH->alias) ? CURMECH->alias : ""); free(public); free(secret); public = NULL; secret = NULL; } plist[mcount] = public; slist[mcount] = secret; } } else { char *public, *secret; if (slist[0]) free(slist[0]); if (!(public = malloc(HEXKEYBYTES + 1))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } if (!(secret = malloc(HEXKEYBYTES + 1))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } __gen_dhkeys(public, secret, short_login_pw); plist[0] = public; slist[0] = secret; } } /* * Make sure that the entered Secure-RPC password(s) match the login * password */ static void cmp_passwd() { char baseprompt[] = "Please enter the login password for"; char prompt[BUFSIZ]; char *en_login_pw = spw->sp_pwdp; char short_en_login_pw[DESCREDPASSLEN + 1]; char *try_en_login_pw; bool_t pwmatch = FALSE; int done = 0, tries = 0, pcount; snprintf(prompt, BUFSIZ, "%s %s:", baseprompt, pw->pw_name); (void) strlcpy(short_en_login_pw, en_login_pw, sizeof (short_en_login_pw)); if (en_login_pw && (strlen(en_login_pw) != 0)) { for (pcount = 0; pcount < rpc_pw_count; pcount++) { char *try_en_rpc_pw; try_en_rpc_pw = crypt(rpc_pws[pcount], short_en_login_pw); if (strcmp(try_en_rpc_pw, short_en_login_pw) == 0) { login_pw = rpc_pws[pcount]; (void) strlcpy(short_login_pw, login_pw, sizeof (short_login_pw)); pwmatch = TRUE; break; } } if (!pwmatch) { /* pw don't match */ while (!done) { /* ask for the pw */ login_pw = getpassphrase(prompt); (void) strlcpy(short_login_pw, login_pw, sizeof (short_login_pw)); if (login_pw && strlen(login_pw)) { /* pw was not empty */ try_en_login_pw = crypt(login_pw, en_login_pw); /* compare the pw's */ if (!(strcmp(try_en_login_pw, en_login_pw))) { /* pw was correct */ return; } else { /* pw was wrong */ if (tries++) { /* Sorry */ fprintf(stderr, "Sorry.\n"); exit(1); } else { /* Try again */ snprintf(prompt, BUFSIZ, "Try again. %s %s:", baseprompt, pw->pw_name); } } } else { /* pw was empty */ if (tries++) { /* Unchanged */ fprintf(stderr, "%s: key-pair(s) unchanged for %s.\n", program_name, pw->pw_name); exit(1); } else { /* Need a password */ snprintf(prompt, BUFSIZ, "Need a password. %s %s:", baseprompt, pw->pw_name); } } } } /* pw match */ return; } else { /* no pw found */ fprintf(stderr, "%s: no passwd found for %s in the shadow passwd entry.\n", program_name, pw->pw_name); exit(1); } } /* Prompt the user for a Secure-RPC password and store it in a cache. */ static void getrpcpws(char *flavor) { char *cur_pw = NULL; char prompt[BUFSIZ + 1]; if (flavor) snprintf(prompt, BUFSIZ, "Please enter the %s Secure-RPC password for %s:", flavor, pw->pw_name); else snprintf(prompt, BUFSIZ, "Please enter the Secure-RPC password for %s:", pw->pw_name); cur_pw = getpass(prompt); if (!cur_pw) { /* No changes */ fprintf(stderr, "%s: key-pair(s) unchanged for %s.\n", program_name, pw->pw_name); exit(1); } rpc_pw_count++; if (!(rpc_pws = (char **)realloc(rpc_pws, sizeof (char *) * rpc_pw_count))) { fprintf(stderr, "%s: Realloc failure.\n", program_name); exit(1); } rpc_pws[rpc_pw_count - 1] = cur_pw; } /* Retrieve the secret key(s) for the user and attempt to decrypt them */ static void getsecrets() { int mcount, scount = 0; int tries = 0; getrpcpws(NULL); if (mechs) { for (mcount = 0; CURMECH; mcount++) { char *secret; int pcount; size_t hexkeylen; hexkeylen = ((CURMECH->keylen / 8) * 2) + 1; if (!(secret = (char *)calloc(hexkeylen, sizeof (char)))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } for (pcount = 0; pcount < rpc_pw_count; pcount++) { if (!getsecretkey_g(netname, CURMECH->keylen, CURMECH->algtype, secret, hexkeylen, rpc_pws[pcount])) continue; if (secret[0] == 0) continue; else break; } tries = 0; getsecrets_tryagain_g: if (secret[0] == 0) { if (!tries) { /* * No existing pw can decrypt * secret key */ getrpcpws(CURMECH->alias); if (!getsecretkey_g(netname, CURMECH->keylen, CURMECH->algtype, secret, hexkeylen, rpc_pws[pcount])) { /* * Could not retreive * secret key, abort */ free(secret); secret = NULL; goto getsecrets_abort; } if (secret[0] == 0) { /* Still no go, ask again */ free(rpc_pws[pcount]); rpc_pw_count--; tries++; printf("Try again. "); fflush(stdout); goto getsecrets_tryagain_g; } else scount++; } else { fprintf(stderr, "%s: key-pair unchanged for %s.\n", program_name, pw->pw_name); exit(1); } } else scount++; getsecrets_abort: slist[mcount] = secret; } } else { char *secret = NULL; if (!(secret = (char *)malloc(HEXKEYBYTES + 1))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } getsecrets_tryagain: if (!getsecretkey(netname, secret, rpc_pws[0])) { fprintf(stderr, "%s: could not get secret key for '%s'\n", program_name, netname); exit(1); } if (secret[0] == 0) { if (!tries) { free(rpc_pws[0]); rpc_pw_count = 0; tries++; printf("Try again. "); fflush(stdout); getrpcpws(NULL); goto getsecrets_tryagain; } else { fprintf(stderr, "%s: key-pair unchanged for %s.\n", program_name, pw->pw_name); exit(1); } } slist[0] = secret; return; } if (!scount) { (void) fprintf(stderr, "%s: could not get nor decrypt any secret keys for '%s'\n", program_name, netname); error_msg(); exit(1); } } /* Register AUTH_DES secret key with keyserv */ static void keylogin_des() { char *secret = slist[0]; struct key_netstarg netst; /* * try to revoke the existing key/credentials, assuming * one exists. this will effectively mark "stale" any * cached credientials... */ if (key_setsecret(secret) < 0) { return; } #ifdef NFS_AUTH /* * it looks like a credential already existed, so try and * revoke any lingering Secure-NFS privledges. */ nra.authtype = AUTH_DES; nra.uid = getuid(); if (_nfssys(NFS_REVAUTH, &nra) < 0) perror("Warning: NFS credentials not destroyed"); #endif /* NFS_AUTH */ (void) memcpy(netst.st_priv_key, secret, HEXKEYBYTES); netst.st_pub_key[0] = '\0'; netst.st_netname = strdup(netname); /* do actual key login */ if (key_setnet(&netst) < 0) { fprintf(stderr, "Could not set %s's secret key\n", netname); fprintf(stderr, "May be the keyserv is down?\n"); } } /* Register a secret key with the keyserv */ static void keylogin(keylen_t keylen, algtype_t algtype) { int mcount; if (mechs) { for (mcount = 0; CURMECH; mcount++) { if (keylen == CURMECH->keylen && algtype == CURMECH->algtype) { if (key_setnet_g(netname, slist[mcount], CURMECH->keylen, NULL, 0, CURMECH->algtype) < 0) fprintf(stderr, "Could not set %s's %s secret key\n", netname, VALID_ALIAS(CURMECH->alias) ? CURMECH->alias : ""); } } } else { if (keylen == 192 && algtype == 0) keylogin_des(); } } /* * fgets is "broken" in that if it reads a NUL character it will * always return EOF for all reads, even when there is data left in * the file. This replacement can deal with NUL's in a calm, rational * manner. */ static char * fgets_ignorenul(char *s, int n, FILE *stream) { int fildes = fileno(stream); int i = 0; int rs = 0; char c; if (fildes < 0) return (NULL); while (i < n - 1) { rs = read(fildes, &c, 1); switch (rs) { case 1: break; case 0: /* EOF */ if (i > 0) s[i] = '\0'; return (NULL); break; default: return (NULL); } switch (c) { case '\0': break; case '\n': s[i] = c; s[++i] = '\0'; return (s); default: if (c != '\0') s[i++] = c; } } s[i] = '\0'; return (s); } /* Write unencrypted secret key into root key file */ static void write_rootkey(char *secret, char *flavor, keylen_t keylen, algtype_t algtype) { char line[MAXROOTKEY_LINE_LEN]; char keyent[MAXROOTKEY_LEN]; algtype_t atent; int rootfd, bakfd, hexkeybytes; bool_t lineone = TRUE; bool_t gotit = FALSE; FILE *rootfile, *bakfile; unlink(ROOTKEY_FILE_BACKUP); if ((rename(ROOTKEY_FILE, ROOTKEY_FILE_BACKUP)) < 0) { if ((bakfd = creat(ROOTKEY_FILE_BACKUP, 0600)) < 0) { perror("Could not create /etc/.rootkey.bak"); goto rootkey_err; } close(bakfd); } if ((rootfd = open(ROOTKEY_FILE, O_WRONLY+O_CREAT, 0600)) < 0) { perror("Could not open /etc/.rootkey for writing"); fprintf(stderr, "Attempting to restore original /etc/.rootkey\n"); rename(ROOTKEY_FILE_BACKUP, ROOTKEY_FILE); goto rootkey_err; } if (!(rootfile = fdopen(rootfd, "w"))) { perror("Could not open /etc/.rootkey for writing"); fprintf(stderr, "Attempting to restore original /etc/.rootkey\n"); close(rootfd); unlink(ROOTKEY_FILE); rename(ROOTKEY_FILE_BACKUP, ROOTKEY_FILE); goto rootkey_err; } if (!(bakfile = fopen(ROOTKEY_FILE_BACKUP, "r"))) { perror("Could not open /etc/.rootkey.bak for reading"); fprintf(stderr, "Attempting to restore original /etc/.rootkey\n"); fclose(rootfile); unlink(ROOTKEY_FILE); rename(ROOTKEY_FILE_BACKUP, ROOTKEY_FILE); goto rootkey_err; } hexkeybytes = ((keylen + 7) / 8) * 2; while (fgets_ignorenul(line, MAXROOTKEY_LINE_LEN, bakfile)) { if (sscanf(line, "%s %d", keyent, &atent) < 2) { /* * No encryption algorithm found in the file * (atent) so default to DES. */ atent = AUTH_DES_ALGTYPE; } /* * 192-bit keys always go on the first line */ if (lineone) { lineone = FALSE; if (keylen == 192) { gotit = TRUE; fprintf(rootfile, "%s\n", secret); } else fprintf(rootfile, "%s", line); fflush(rootfile); } else { if ((strlen(keyent) == hexkeybytes) && (atent == algtype)) { /* * Silently remove lines with the same * keylen/algtype */ if (gotit) continue; else gotit = TRUE; fprintf(rootfile, "%s %d\n", secret, algtype); } else fprintf(rootfile, "%s", line); fflush(rootfile); } } /* Append key to rootkey file */ if (!gotit) { if (keylen == 192) fprintf(rootfile, "%s\n", secret); else { if (lineone) fprintf(rootfile, "\n"); fprintf(rootfile, "%s %d\n", secret, algtype); } } fflush(rootfile); fclose(rootfile); fclose(bakfile); unlink(ROOTKEY_FILE_BACKUP); return; rootkey_err: fprintf(stderr, "WARNING: Could not write %s key to /etc/.rootkey\n", flavor); } /* Store new key information in the specified name service */ static void storekeys() { int mcount, ucount = 0; char *ypmaster, *ypdomain = NULL, pkent[MAXPKENTLEN]; nis_name nis_princ; /* Setup */ switch (dest_service) { case PK_LDAP: break; case PK_YP: yp_get_default_domain(&ypdomain); if (yp_master(ypdomain, PKMAP, &ypmaster) != 0) { fprintf(stderr, "%s: cannot find master of NIS publickey database\n", program_name); exit(1); } fprintf(stdout, "Sending key change request to %s ...\n", ypmaster); break; case PK_FILES: if (geteuid() != 0) { fprintf(stderr, "%s: non-root users cannot change their key-pair in %s\n", program_name, PKFILE); exit(1); } break; default: fprintf(stderr, "could not update; database %d unknown\n", dest_service); exit(1); } if (mechs) { for (mcount = 0; CURMECH; mcount++) { char authtype[MECH_MAXATNAME]; if (!plist[mcount] && !clist[mcount]) continue; __nis_mechalias2authtype(CURMECH->alias, authtype, MECH_MAXATNAME); if (!authtype) { fprintf(stderr, "Could not generate auth_type for %s.\n", CURMECH->alias); continue; } snprintf(pkent, MAXPKENTLEN, "%s:%s:%d", plist[mcount], clist[mcount], CURMECH->algtype); switch (dest_service) { case PK_LDAP: if (ldap_update(CURMECH->alias, netname, plist[mcount], clist[mcount], login_pw)) fprintf(stderr, "%s: unable to update %s key in LDAP database\n", program_name, authtype); else ucount++; break; case PK_YP: /* Should never get here. */ break; case PK_FILES: /* Should never get here. */ break; } } } else { int status = 0; assert(plist[0] && clist[0]); snprintf(pkent, MAXPKENTLEN, "%s:%s", plist[0], clist[0]); switch (dest_service) { case PK_LDAP: if (ldap_update("dh192-0", netname, plist[0], clist[0], login_pw)) { fprintf(stderr, "%s: unable to update %s key in LDAP database\n", program_name); exit(1); } break; case PK_YP: if (status = yp_update(ypdomain, PKMAP, YPOP_STORE, netname, strlen(netname), pkent, strlen(pkent))) { fprintf(stderr, "%s: unable to update NIS database (%u): %s\n", program_name, status, yperr_string(status)); exit(1); } break; case PK_FILES: if (localupdate(netname, PKFILE, YPOP_STORE, pkent)) { fprintf(stderr, "%s: hence, unable to update publickey database\n", program_name); exit(1); } break; default: /* Should never get here */ assert(0); } return; } if (!ucount) { fprintf(stderr, "%s: unable to update any key-pairs for %s.\n", program_name, pw->pw_name); exit(1); } } void addmechtolist(char *mechtype) { mechanism_t **realmechlist; int i; if (realmechlist = __nis_get_mechanisms(FALSE)) { /* Match requested mech with list */ for (i = 0; realmechlist[i]; i++) { if (realmechlist[i]->alias) if (strcmp(realmechlist[i]->alias, mechtype) == 0) { /* * Match, add it to the mechs. * Don't worry about qop or * secserv since they are not * used by chkey. */ numspecmech++; if ((mechs = (mechanism_t **)realloc(mechs, sizeof (mechanism_t *) * (numspecmech + 1))) == NULL) { perror("Can not change keys"); exit(1); } if ((mechs[numspecmech - 1] = (mechanism_t *)malloc( sizeof (mechanism_t))) == NULL) { perror("Can not change keys"); exit(1); } if (realmechlist[i]->mechname) mechs[numspecmech - 1]->mechname = strdup(realmechlist[i]->mechname); if (realmechlist[i]->alias) mechs[numspecmech - 1]->alias = strdup(realmechlist[i]->alias); mechs[numspecmech - 1]->keylen = realmechlist[i]->keylen; mechs[numspecmech - 1]->algtype = realmechlist[i]->algtype; mechs[numspecmech] = NULL; __nis_release_mechanisms(realmechlist); return; } } fprintf(stderr, "WARNING: Mechanism '%s' not configured, skipping...\n", mechtype); __nis_release_mechanisms(realmechlist); return; } fprintf(stderr, "WARNING: Mechanism '%s' not configured, skipping...\n", mechtype); } int main(int argc, char **argv) { int c, mcount; uid_t uid; uid_t orig_euid; char *service = NULL; program_name = argv[0]; mechs = __nis_get_mechanisms(FALSE); while ((c = getopt(argc, argv, "fps:m:")) != -1) { switch (c) { case 'f': /* * Not documented as of on1093. * Temporarily supported */ force++; break; case 'p': makenew = FALSE; break; case 's': if (!service) service = strdup(optarg); else usage(); break; case 'm': if (mechs && specmech == FALSE) { __nis_release_mechanisms(mechs); mechs = NULL; } specmech = TRUE; addmechtolist(optarg); break; default: usage(); } } if (optind < argc) usage(); dest_service = get_pk_source(service); if (!(netname = malloc(MAXNETNAMELEN + 1))) { fprintf(stderr, "%s: Malloc failure.\n", program_name); exit(1); } if (!__getnetnamebyuid(netname, uid = getuid())) { fprintf(stderr, "%s: cannot generate netname for uid %d\n", program_name, uid); exit(1); } sec_domain = strdup(strchr(netname, '@') + 1); getdomainname(local_domain, MAXNETNAMELEN); if (makenew) fprintf(stdout, "Generating new key for '%s'.\n", netname); else fprintf(stdout, "Reencrypting key for '%s'.\n", netname); if (mechs) { if (dest_service == PK_YP || dest_service == PK_FILES) { fprintf(stderr, "%s: can not add non-DES public keys to %s, skipping.\n", program_name, service); __nis_release_mechanisms(mechs); mechs = NULL; initkeylist(TRUE); } else initkeylist(FALSE); } else initkeylist(TRUE); uid = getuid(); orig_euid = geteuid(); /* Get password information */ if ((pw = getpwuid(uid)) == NULL) { fprintf(stderr, "%s: Can not find passwd information for %d.\n", program_name, uid); exit(1); } /* Set eUID to user */ seteuid(uid); /* Obtain a list of decrypted secret keys */ getsecrets(); /* Keylogin user if not already done */ if (mechs) { int mcount; for (mcount = 0; CURMECH; mcount++) { keylen_t keylen = CURMECH->keylen; algtype_t algtype = CURMECH->algtype; if (!key_secretkey_is_set_g(keylen, algtype) && slist[mcount]) { keylogin(CURMECH->keylen, CURMECH->algtype); if ((uid == 0) && (makenew == FALSE)) write_rootkey(slist[mcount], VALID_ALIAS(CURMECH->alias) ? CURMECH->alias : "", keylen, algtype); } } } else { assert(slist[0]); if (!key_secretkey_is_set()) { keylogin_des(); if ((uid == 0) && (makenew == FALSE)) write_rootkey(slist[0], "des", 192, 0); } } /* Set eUID back to root */ (void) seteuid(orig_euid); /* * Call getspnam() after the keylogin has been done so we have * the best chance of having read access to the encrypted pw. * * The eUID must be 0 for the getspnam() so the name service * switch can handle the following eUID sensitive cases: * * files/compat: read /etc/shadow * */ if ((spw = getspnam(pw->pw_name)) == 0) { /* Set eUID back to user */ (void) seteuid(uid); (void) fprintf(stderr, "%s: cannot find shadow entry for %s.\n", program_name, pw->pw_name); exit(1); } /* Set eUID back to user */ (void) seteuid(uid); if (strcmp(spw->sp_pwdp, NOPWDRTR) == 0) { (void) fprintf(stderr, "%s: do not have read access to the passwd field for %s\n", program_name, pw->pw_name); exit(1); } /* * force will be only supported for a while * -- it is NOT documented as of s1093 */ if (force) { char *prompt = "Please enter New password:"; login_pw = getpassphrase(prompt); (void) strlcpy(short_login_pw, login_pw, sizeof (short_login_pw)); if (!login_pw || !(strlen(login_pw))) { fprintf(stderr, "%s: key-pair(s) unchanged for %s.\n", program_name, pw->pw_name); exit(1); } } else { /* * Reconsile rpc_pws and login_pw. * * This function will either return with login_pw == rpc_pw * (and thus, the new pw to encrypt keys) or it will exit. */ cmp_passwd(); } if (makenew) makenewkeys(); else getpublics(); encryptkeys(); storekeys(); if (makenew) { if (uid == 0) { if (mechs) { for (mcount = 0; CURMECH; mcount++) { if (!slist[mcount]) continue; write_rootkey(slist[mcount], CURMECH->alias, CURMECH->keylen, CURMECH->algtype); } } else { assert(slist[0]); write_rootkey(slist[0], "des", 192, 0); } } if (mechs) { for (mcount = 0; CURMECH; mcount++) keylogin(CURMECH->keylen, CURMECH->algtype); } else keylogin_des(); } return (0); }