/* * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include extern char *crypt(); extern long random(); extern char *getpassphrase(); extern char *program_name; static const char *CRED_TABLE = "cred.org_dir"; #define ROOTKEY_FILE "/etc/.rootkey" #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif #define PK_FILES 1 #define PK_YP 2 #define PK_LDAP 4 #define LDAP_BINDDN_DEFAULT "cn=Directory Manager" #define PROMPTGET_SUCCESS 1 #define PROMPTGET_FAIL -1 #define PROMPTGET_MEMORY_FAIL -2 #define PASSWD_UNMATCHED -3 #define FREE_CREDINFO(s) \ if ((s)) { (void) memset((s), 0, strlen((s))); } /* ************************ switch functions *************************** */ /* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */ #define DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE} static struct __nsw_lookup lookup_files = {"files", DEF_ACTION, NULL, NULL}, lookup_nis = {"nis", DEF_ACTION, NULL, &lookup_files}; static struct __nsw_switchconfig publickey_default = {0, "publickey", 2, &lookup_nis}; static int get_ldap_bindDN(char **); static int get_ldap_bindPassword(char **); /* * Prompt the users for a ldap bind DN. If users do not enter a value but just * simply hit the return key, the default bindDN "cn=Directory Manager" * will be used. */ static int get_ldap_bindDN(char **ret_bindDN) { char bindDN[BUFSIZ]; char prompt[BUFSIZ]; int blen, pos; /* set the initial value for bindDN buffer */ (void) memset(bindDN, 0, BUFSIZ); (void) snprintf(prompt, BUFSIZ, "\nThe LDAP bind DN and password are required for this update.\n" "If you are not sure what values to enter, please contact your\n" "LDAP administrator.\n\nPlease enter LDAP bind DN [%s]: ", LDAP_BINDDN_DEFAULT); printf(prompt); if (fgets(bindDN, sizeof (bindDN), stdin) == NULL) { (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ); } blen = strlen(bindDN); /* Check if the buffer ends with a newline */ if ((blen > 0) && (bindDN[blen - 1] == '\n')) { bindDN[blen - 1] = '\0'; blen -= 1; } /* Remove the white spaces */ if (blen > 0) { for (pos = blen - 1; pos >= 0; pos--) { if (isspace(bindDN[pos])) bindDN[pos] = '\0'; else break; } } /* Use the default bindDN, if the buffer contains no characters */ if (strlen(bindDN) == 0) (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ); if ((*ret_bindDN = (char *)malloc(strlen(bindDN)+1)) == NULL) { (void) memset(bindDN, 0, BUFSIZ); return (PROMPTGET_MEMORY_FAIL); } (void) strlcpy(*ret_bindDN, bindDN, strlen(bindDN)+1); /* Clean up and erase the credential info */ (void) memset(bindDN, 0, BUFSIZ); return (PROMPTGET_SUCCESS); } /* * Prompt the user for a ldap bind password. */ static int get_ldap_bindPassword(char **ret_bindPass) { char bindPassword[BUFSIZ]; char prompt[BUFSIZ]; char *bindPass = NULL; /* set the initial value for bindPassword buffer */ (void) memset(bindPassword, 0, BUFSIZ); *ret_bindPass = NULL; (void) snprintf(prompt, BUFSIZ, "Please enter LDAP bind password: "); bindPass = getpassphrase(prompt); if (bindPass == NULL) return (PROMPTGET_FAIL); (void) strlcpy(bindPassword, bindPass, BUFSIZ); /* clean the static buffer returned from getpassphrase call */ (void) memset(bindPass, 0, strlen(bindPass)); bindPass = NULL; /* * Re-enter the bind passowrd and compare it with the one * from previous entered. */ (void) snprintf(prompt, BUFSIZ, "Re-enter LDAP bind password to confirm: "); bindPass = getpassphrase(prompt); if (bindPass == NULL) { (void) memset(bindPassword, 0, BUFSIZ); return (PASSWD_UNMATCHED); } if (strcmp(bindPass, bindPassword) != 0) { (void) memset(bindPassword, 0, BUFSIZ); (void) memset(bindPass, 0, strlen(bindPass)); return (PASSWD_UNMATCHED); } else { (void) memset(bindPass, 0, strlen(bindPass)); if ((*ret_bindPass = (char *)malloc(strlen(bindPassword)+1)) == NULL) { (void) memset(bindPassword, 0, BUFSIZ); return (PROMPTGET_MEMORY_FAIL); } (void) strlcpy(*ret_bindPass, bindPassword, strlen(bindPassword)+1); /* Clean up and erase the credential info */ (void) memset(bindPassword, 0, BUFSIZ); return (PROMPTGET_SUCCESS); } } char * switch_policy_str(struct __nsw_switchconfig *conf) { struct __nsw_lookup *look; static char policy[256]; /* 256 is enough for (nis, files...etc) */ int previous = 0; memset((char *)policy, 0, 256); for (look = conf->lookups; look; look = look->next) { if (previous) strcat(policy, " "); strcat(policy, look->service_name); previous = 1; } return (policy); } int no_switch_policy(struct __nsw_switchconfig *conf) { return (conf == NULL || conf->lookups == NULL); } int is_switch_policy(struct __nsw_switchconfig *conf, char *target) { return (conf && conf->lookups && strcmp(conf->lookups->service_name, target) == 0 && conf->lookups->next == NULL); } char * first_and_only_switch_policy(char *policy, struct __nsw_switchconfig *default_conf, char *head_msg) { struct __nsw_switchconfig *conf; enum __nsw_parse_err perr; int policy_correct = 1; char *target_service = 0; int use_default = 0; if (default_conf == 0) default_conf = &publickey_default; conf = __nsw_getconfig(policy, &perr); if (no_switch_policy(conf)) { use_default = 1; conf = default_conf; } target_service = conf->lookups->service_name; if (conf->lookups->next != NULL) { policy_correct = 0; if (use_default) { (void) fprintf(stderr, "\n%s\n There is no publickey entry in %s.\n", head_msg, __NSW_CONFIG_FILE); (void) fprintf(stderr, "The default publickey policy is \"publickey: %s\".\n", switch_policy_str(default_conf)); } else (void) fprintf(stderr, "\n%s\nThe publickey entry in %s is \"publickey: %s\".\n", head_msg, __NSW_CONFIG_FILE, switch_policy_str(conf)); } if (policy_correct == 0) (void) fprintf(stderr, "I cannot figure out which publickey database you want to update.\n"); if (!use_default && conf) __nsw_freeconfig(conf); if (policy_correct) return (target_service); else return (0); } int check_switch_policy(char *policy, char *target_service, struct __nsw_switchconfig *default_conf, char *head_msg, char *tail_msg) { struct __nsw_switchconfig *conf; enum __nsw_parse_err perr; int policy_correct = 1; if (default_conf == 0) default_conf = &publickey_default; conf = __nsw_getconfig(policy, &perr); if (no_switch_policy(conf)) { if (!is_switch_policy(default_conf, target_service)) { (void) fprintf(stderr, "\n%s\nThere is no publickey entry in %s.\n", head_msg, __NSW_CONFIG_FILE); (void) fprintf(stderr, "The default publickey policy is \"publickey: %s\".\n", switch_policy_str(default_conf)); policy_correct = 0; } } else if (!is_switch_policy(conf, target_service)) { (void) fprintf(stderr, "\n%s\nThe publickey entry in %s is \"publickey: %s\".\n", head_msg, __NSW_CONFIG_FILE, switch_policy_str(conf)); policy_correct = 0; } /* should we exit ? */ if (policy_correct == 0) (void) fprintf(stderr, "It should be \"publickey: %s\"%s\n\n", target_service, tail_msg); if (conf) __nsw_freeconfig(conf); return (policy_correct); } int get_pk_source(char *pk_service) { int db = 0, got_from_switch = 0; /* No service specified, try to figure out from switch */ if (pk_service == 0) { pk_service = first_and_only_switch_policy("publickey", 0, "ERROR:"); if (pk_service == 0) return (0); (void) fprintf(stdout, "Updating %s publickey database.\n", pk_service); got_from_switch = 1; } if (strcmp(pk_service, "ldap") == 0) db = PK_LDAP; else if (strcmp(pk_service, "nis") == 0) db = PK_YP; else if (strcmp(pk_service, "files") == 0) db = PK_FILES; else return (0); /* * If we didn't get service name from switch, check switch * and print warning about it source of publickeys if not unique */ if (got_from_switch == 0) check_switch_policy("publickey", pk_service, 0, "WARNING:", db == PK_FILES ? "" : "; add 'files' if you want the 'nobody' key."); return (db); /* all passed */ } /* ***************************** keylogin stuff *************************** */ int keylogin(char *netname, char *secret) { struct key_netstarg netst; netst.st_pub_key[0] = 0; memcpy(netst.st_priv_key, secret, HEXKEYBYTES); netst.st_netname = netname; #ifdef NFS_AUTH nra.authtype = AUTH_DES; /* only revoke DES creds */ nra.uid = getuid(); /* use the real uid */ if (_nfssys(NFS_REVAUTH, &nra) < 0) { perror("Warning: NFS credentials not destroyed"); err = 1; } #endif /* do actual key login */ if (key_setnet(&netst) < 0) { (void) fprintf(stderr, "Could not set %s's secret key\n", netname); (void) fprintf(stderr, "May be the keyserv is down?\n"); return (0); } return (1); } nis_object * init_entry() { static nis_object obj; static entry_col cred_data[10]; entry_obj *eo; memset((char *)(&obj), 0, sizeof (obj)); memset((char *)(cred_data), 0, sizeof (entry_col) * 10); obj.zo_name = "cred"; obj.zo_group = ""; obj.zo_ttl = 43200; obj.zo_data.zo_type = NIS_ENTRY_OBJ; eo = &(obj.EN_data); eo->en_type = "cred_tbl"; eo->en_cols.en_cols_val = cred_data; eo->en_cols.en_cols_len = 5; cred_data[4].ec_flags |= EN_CRYPT; return (&obj); } static char *attrFilter[] = { "objectclass", "nispublickey", "nissecretkey", (char *)NULL }; /* Determines if there is a NisKeyObject objectclass in a given entry */ static int ldap_keyobj_exist(ns_ldap_entry_t *entry) { char **fattrs; fattrs = __ns_ldap_getAttr(entry, "objectClass"); if (fattrs == NULL) return (1); while (*fattrs) { if (strcasecmp("NisKeyObject", *fattrs) == 0) return (1); fattrs++; } return (0); } static char *keyAttrs[] = { "nispublickey", "nissecretkey", NULL }; /* * Replace or append new attribute value(s) to an attribute. * Don't care about memory leaks, because program is short running. */ static int ldap_attr_mod(ns_ldap_entry_t *entry, char *mechname, char *public, ns_ldap_attr_t **pkeyattrs, char *crypt, ns_ldap_attr_t **ckeyattrs) { char **alist[2]; char *keys[2]; char *mechfilter; int mechfilterlen; int q = 0; int i, j; int keycount[] = {0, 0}; ns_ldap_attr_t *attrs; keys[0] = public; keys[1] = crypt; mechfilter = (char *)malloc(strlen(mechname) + 3); if (mechfilter == NULL) return (0); sprintf(mechfilter, "{%s}", mechname); mechfilterlen = strlen(mechfilter); for (q = 0; keyAttrs[q] != NULL; q++) { int found = 0; for (i = 0; i < entry->attr_count; i++) { int rep = 0; ns_ldap_attr_t *attr = entry->attr_pair[i]; char *name = attr->attrname; int count = 0; if (strcasecmp(keyAttrs[q], name) == 0) { found++; count = attr->value_count; alist[q] = (char **)malloc(sizeof (char *) * (count + 1)); if (alist[q] == NULL) return (0); alist[q][attr->value_count] = NULL; for (j = 0; j < attr->value_count; j++) { char *val = attr->attrvalue[j]; if (strncasecmp(val, mechfilter, mechfilterlen) == 0) { /* Replace entry */ rep++; alist[q][j] = keys[q]; } else alist[q][j] = val; ++keycount[q]; } if (!rep) { /* Add entry to list */ alist[q] = (char **)realloc(alist[q], sizeof (char *) * (count + 2)); if (alist[q] == NULL) return (0); alist[q][attr->value_count + 1] = NULL; alist[q][attr->value_count] = keys[q]; ++keycount[q]; } } } if (!found) { /* Attribute does not exist, add entry anyways */ alist[q] = (char **)malloc(sizeof (char *) * 2); if (alist[q] == NULL) return (0); alist[q][0] = keys[q]; alist[q][1] = NULL; ++keycount[q]; } } if ((attrs = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t))) == NULL) return (0); attrs->attrname = "nisPublicKey"; attrs->attrvalue = alist[0]; attrs->value_count = keycount[0]; *pkeyattrs = attrs; if ((attrs = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t))) == NULL) return (0); attrs->attrname = "nisSecretKey"; attrs->attrvalue = alist[1]; attrs->value_count = keycount[1]; *ckeyattrs = attrs; return (1); } /* * Do the actual Add or update of attributes in attrs. * The parameter 'update4host' is a flag that tells the function which * DN and password should be used to bind to ldap. If it is an update * for a host (update4host > 0), the two parameters "bindDN" and * "bindPasswd" would be used to bind as the directory manager, * otherwise "dn" and "passwd" would be used to bind as an individual * user. */ static void update_ldap_attr(const char *dn, ns_ldap_attr_t **attrs, const char *passwd, int add, int update4host, const char *bindDN, const char *bindPasswd) { int ldaprc; int authstried = 0; char *msg; char *ldap_pw; char **certpath = NULL; ns_auth_t **app; ns_auth_t **authpp = NULL; ns_auth_t *authp = NULL; ns_cred_t *credp; ns_ldap_error_t *errorp = NULL; int status; if ((credp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t))) == NULL) { fprintf(stderr, "Can not allocate cred buffer.\n"); goto out; } /* * if this is an update for host, use the bindDN from the * command prompt, otherwise use user's DN directly. */ if (update4host) credp->cred.unix_cred.userID = strdup(bindDN); else credp->cred.unix_cred.userID = strdup(dn); if (credp->cred.unix_cred.userID == NULL) { fprintf(stderr, "Memory allocation failure (userID)\n"); goto out; } if (update4host) { credp->cred.unix_cred.passwd = strdup(bindPasswd); } else { if (passwd) credp->cred.unix_cred.passwd = strdup(passwd); else { /* Make sure a valid password is received. */ status = get_ldap_bindPassword(&ldap_pw); if (status != PROMPTGET_SUCCESS) { if (!ldap_pw) free(ldap_pw); goto out; } credp->cred.unix_cred.passwd = ldap_pw; } } if (credp->cred.unix_cred.passwd == NULL) { fprintf(stderr, "Memory allocation failure (passwd)\n"); goto out; } /* get host certificate path, if one is configured */ if (__ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P, (void ***)&certpath, &errorp) != NS_LDAP_SUCCESS) goto out; if (certpath && *certpath) credp->hostcertpath = *certpath; /* Load the service specific authentication method */ if (__ns_ldap_getServiceAuthMethods("keyserv", &authpp, &errorp) != NS_LDAP_SUCCESS) goto out; /* * if authpp is null, there is no serviceAuthenticationMethod * try default authenticationMethod */ if (authpp == NULL) { if (__ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp, &errorp) != NS_LDAP_SUCCESS) goto out; } /* * if authpp is still null, then can not authenticate, log * error message and return error */ if (authpp == NULL) { fprintf(stderr, "No LDAP authentication method configured.\n" " configured.\n"); goto out; } /* * Walk the array and try all authentication methods in order except * for "none". */ for (app = authpp; *app; app++) { authp = *app; /* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */ if (authp->type == NS_LDAP_AUTH_NONE) continue; authstried++; credp->auth.type = authp->type; credp->auth.tlstype = authp->tlstype; credp->auth.saslmech = authp->saslmech; credp->auth.saslopt = authp->saslopt; if (add == TRUE) ldaprc = __ns_ldap_addAttr("publickey", dn, (const ns_ldap_attr_t * const *)attrs, credp, NULL, &errorp); else ldaprc = __ns_ldap_repAttr("publickey", dn, (const ns_ldap_attr_t * const *)attrs, credp, NULL, &errorp); if (ldaprc == NS_LDAP_SUCCESS) { /* clean up ns_cred_t structure in memory */ if (credp != NULL) (void) __ns_ldap_freeCred(&credp); return; } /* XXX add checking for cases of authentication errors */ if ((ldaprc == NS_LDAP_INTERNAL) && ((errorp->status == LDAP_INAPPROPRIATE_AUTH) || (errorp->status == LDAP_INVALID_CREDENTIALS))) { fprintf(stderr, "LDAP authentication failed.\n"); goto out; } } if (authstried == 0) fprintf(stderr, "No legal authentication method configured.\n"); out: /* clean up ns_cred_t structure in memory */ if (credp != NULL) { (void) __ns_ldap_freeCred(&credp); } if (errorp) { __ns_ldap_err2str(errorp->status, &msg); fprintf(stderr, "LDAP error: %s.\n", msg); } fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } /* * Update LDAP nisplublickey entry with new key information via SLDAP. * Free and clean up memory that stores credential data soon after * they are not used or an error comes up. */ int ldap_update(char *mechname, char *netname, char *public, char *crypt, char *passwd) { char *netnamecpy; char *id; char *domain; char *dn; char *db; char *filter; ns_ldap_error_t *errorp; char *pkeyatval, *ckeyatval; ns_ldap_result_t *res; ns_ldap_attr_t *pattrs, *cattrs; int update4host = FALSE; char *bindDN = NULL; char *bindPasswd = NULL; int status; /* Generate DN */ if ((netnamecpy = strdup(netname)) == NULL) return (0); if (((id = strchr(netnamecpy, '.')) == NULL) || ((domain = strchr(netnamecpy, '@')) == NULL)) return (0); else { *domain++ = '\0'; *id++ = '\0'; id = strdup(id); if (id == NULL) { free(netnamecpy); fprintf(stderr, "LDAP memory error (id)\n"); return (0); } domain = strdup(domain); if (domain == NULL) { free(netnamecpy); free(id); fprintf(stderr, "LDAP memory error (domain)\n"); return (0); } free(netnamecpy); } if (isdigit(*id)) { /* We be user. */ __ns_ldap_uid2dn(id, &dn, NULL, &errorp); if (dn == NULL) { fprintf(stderr, "Could not obtain LDAP dn\n"); fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } db = "passwd"; filter = (char *)malloc(strlen(id) + 13); if (filter) sprintf(filter, "(uidnumber=%s)", id); else { fprintf(stderr, "Can not allocate filter buffer.\n"); fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } } else { /* We be host. */ update4host = TRUE; __ns_ldap_host2dn(id, NULL, &dn, NULL, &errorp); if (dn == NULL) { fprintf(stderr, "Could not obtain LDAP dn\n"); fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } db = "hosts"; filter = (char *)malloc(strlen(id) + 6); if (filter) sprintf(filter, "(cn=%s)", id); else { fprintf(stderr, "Can not allocate filter buffer.\n"); fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } /* Prompt for ldap bind DN for entry udpates */ status = get_ldap_bindDN(&bindDN); if (status != PROMPTGET_SUCCESS) { FREE_CREDINFO(bindDN); fprintf(stderr, "Failed to get a valid LDAP bind DN.\n" "%s: key-pair(s) unchanged.\n", program_name); exit(1); } /* Prompt for ldap bind password */ status = get_ldap_bindPassword(&bindPasswd); if (status != PROMPTGET_SUCCESS) { FREE_CREDINFO(bindPasswd); FREE_CREDINFO(bindDN); fprintf(stderr, "Failed to get a valid LDAP bind password." "\n%s: key-pair(s) unchanged.\n", program_name); exit(1); } } /* Construct attribute values */ pkeyatval = (char *)malloc(strlen(mechname) + strlen(public) + 3); if (pkeyatval == NULL) { FREE_CREDINFO(bindPasswd); FREE_CREDINFO(bindDN); fprintf(stderr, "LDAP memory error (pkeyatval)\n"); fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } sprintf(pkeyatval, "{%s}%s", mechname, public); ckeyatval = (char *)malloc(strlen(mechname) + strlen(crypt) + 3); if (ckeyatval == NULL) { FREE_CREDINFO(pkeyatval); FREE_CREDINFO(bindPasswd); FREE_CREDINFO(bindDN); fprintf(stderr, "LDAP memory error (pkeyatval)\n"); fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } sprintf(ckeyatval, "{%s}%s", mechname, crypt); /* Does entry exist? */ if ((__ns_ldap_list(db, filter, NULL, (const char **)attrFilter, NULL, 0, &res, &errorp, NULL, NULL) == NS_LDAP_SUCCESS) && res == NULL) { FREE_CREDINFO(ckeyatval); FREE_CREDINFO(pkeyatval); FREE_CREDINFO(bindPasswd); FREE_CREDINFO(bindDN); fprintf(stderr, "LDAP entry does not exist.\n"); fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } /* Entry exists, modify attributes for public and secret keys */ /* Is there a NisKeyObject in entry? */ if (!ldap_keyobj_exist(&res->entry[0])) { /* Add NisKeyObject objectclass and the keys */ char **newattr; ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */ /* set objectclass */ newattr = (char **)calloc(2, sizeof (char *)); newattr[0] = "NisKeyObject"; newattr[1] = NULL; if ((attrs[0] = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t))) == NULL) { FREE_CREDINFO(ckeyatval); FREE_CREDINFO(pkeyatval); FREE_CREDINFO(bindPasswd); FREE_CREDINFO(bindDN); fprintf(stderr, "Memory allocation failed\n"); fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } attrs[0]->attrname = "objectClass"; attrs[0]->attrvalue = newattr; attrs[0]->value_count = 1; /* set publickey */ newattr = (char **)calloc(2, sizeof (char *)); newattr[0] = pkeyatval; newattr[1] = NULL; if ((attrs[1] = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t))) == NULL) { FREE_CREDINFO(ckeyatval); FREE_CREDINFO(pkeyatval); FREE_CREDINFO(bindPasswd); FREE_CREDINFO(bindDN); fprintf(stderr, "Memory allocation failed\n"); fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } attrs[1]->attrname = "nisPublicKey"; attrs[1]->attrvalue = newattr; attrs[1]->value_count = 1; /* set privatekey */ newattr = (char **)calloc(2, sizeof (char *)); newattr[0] = ckeyatval; newattr[1] = NULL; if ((attrs[2] = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t))) == NULL) { FREE_CREDINFO(ckeyatval); FREE_CREDINFO(pkeyatval); FREE_CREDINFO(bindPasswd); FREE_CREDINFO(bindDN); fprintf(stderr, "Memory allocation failed\n"); fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } attrs[2]->attrname = "nisSecretKey"; attrs[2]->attrvalue = newattr; attrs[2]->value_count = 1; /* terminator */ attrs[3] = NULL; update_ldap_attr(dn, attrs, passwd, TRUE, update4host, bindDN, bindPasswd); } else { /* object class already exists, replace keys */ ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */ if (!ldap_attr_mod(&res->entry[0], mechname, pkeyatval, &pattrs, ckeyatval, &cattrs)) { FREE_CREDINFO(ckeyatval); FREE_CREDINFO(pkeyatval); FREE_CREDINFO(bindPasswd); FREE_CREDINFO(bindDN); fprintf(stderr, "Could not generate LDAP attribute list.\n"); fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name); exit(1); } attrs[0] = pattrs; attrs[1] = cattrs; attrs[2] = NULL; update_ldap_attr(dn, attrs, passwd, FALSE, update4host, bindDN, bindPasswd); } FREE_CREDINFO(ckeyatval); FREE_CREDINFO(pkeyatval); FREE_CREDINFO(bindPasswd); FREE_CREDINFO(bindDN); return (0); }