8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / keyserv / chkey_common.c
blobd8d6e22beb3afc5e2b2707f2a2e43344d2fbf9c3
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <strings.h>
30 #include <pwd.h>
31 #include <shadow.h>
32 #include <netdb.h>
33 #include <mp.h>
34 #include <rpcsvc/nis.h>
35 #include <rpc/key_prot.h>
36 #include <nsswitch.h>
37 #include <ns_sldap.h>
39 extern char *crypt();
40 extern long random();
41 extern char *getpassphrase();
42 extern char *program_name;
43 static const char *CRED_TABLE = "cred.org_dir";
45 #define ROOTKEY_FILE "/etc/.rootkey"
47 #ifndef MAXHOSTNAMELEN
48 #define MAXHOSTNAMELEN 256
49 #endif
51 #define PK_FILES 1
52 #define PK_YP 2
53 #define PK_LDAP 4
55 #define LDAP_BINDDN_DEFAULT "cn=Directory Manager"
56 #define PROMPTGET_SUCCESS 1
57 #define PROMPTGET_FAIL -1
58 #define PROMPTGET_MEMORY_FAIL -2
59 #define PASSWD_UNMATCHED -3
61 #define FREE_CREDINFO(s) \
62 if ((s)) { (void) memset((s), 0, strlen((s))); }
65 /* ************************ switch functions *************************** */
67 /* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */
68 #define DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE}
70 static struct __nsw_lookup lookup_files = {"files", DEF_ACTION, NULL, NULL},
71 lookup_nis = {"nis", DEF_ACTION, NULL, &lookup_files};
72 static struct __nsw_switchconfig publickey_default =
73 {0, "publickey", 2, &lookup_nis};
75 static int get_ldap_bindDN(char **);
76 static int get_ldap_bindPassword(char **);
79 * Prompt the users for a ldap bind DN. If users do not enter a value but just
80 * simply hit the return key, the default bindDN "cn=Directory Manager"
81 * will be used.
83 static int
84 get_ldap_bindDN(char **ret_bindDN) {
86 char bindDN[BUFSIZ];
87 char prompt[BUFSIZ];
88 int blen, pos;
90 /* set the initial value for bindDN buffer */
91 (void) memset(bindDN, 0, BUFSIZ);
93 (void) snprintf(prompt, BUFSIZ,
94 "\nThe LDAP bind DN and password are required for this update.\n"
95 "If you are not sure what values to enter, please contact your\n"
96 "LDAP administrator.\n\nPlease enter LDAP bind DN [%s]: ",
97 LDAP_BINDDN_DEFAULT);
99 printf(prompt);
101 if (fgets(bindDN, sizeof (bindDN), stdin) == NULL) {
102 (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ);
105 blen = strlen(bindDN);
107 /* Check if the buffer ends with a newline */
108 if ((blen > 0) && (bindDN[blen - 1] == '\n')) {
109 bindDN[blen - 1] = '\0';
110 blen -= 1;
113 /* Remove the white spaces */
114 if (blen > 0) {
115 for (pos = blen - 1; pos >= 0; pos--) {
116 if (isspace(bindDN[pos]))
117 bindDN[pos] = '\0';
118 else
119 break;
123 /* Use the default bindDN, if the buffer contains no characters */
124 if (strlen(bindDN) == 0)
125 (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ);
127 if ((*ret_bindDN = (char *)malloc(strlen(bindDN)+1)) == NULL) {
128 (void) memset(bindDN, 0, BUFSIZ);
129 return (PROMPTGET_MEMORY_FAIL);
132 (void) strlcpy(*ret_bindDN, bindDN, strlen(bindDN)+1);
134 /* Clean up and erase the credential info */
135 (void) memset(bindDN, 0, BUFSIZ);
137 return (PROMPTGET_SUCCESS);
142 * Prompt the user for a ldap bind password.
144 static int
145 get_ldap_bindPassword(char **ret_bindPass) {
147 char bindPassword[BUFSIZ];
148 char prompt[BUFSIZ];
149 char *bindPass = NULL;
151 /* set the initial value for bindPassword buffer */
152 (void) memset(bindPassword, 0, BUFSIZ);
153 *ret_bindPass = NULL;
155 (void) snprintf(prompt, BUFSIZ,
156 "Please enter LDAP bind password: ");
158 bindPass = getpassphrase(prompt);
160 if (bindPass == NULL)
161 return (PROMPTGET_FAIL);
163 (void) strlcpy(bindPassword, bindPass, BUFSIZ);
165 /* clean the static buffer returned from getpassphrase call */
166 (void) memset(bindPass, 0, strlen(bindPass));
167 bindPass = NULL;
170 * Re-enter the bind passowrd and compare it with the one
171 * from previous entered.
173 (void) snprintf(prompt, BUFSIZ,
174 "Re-enter LDAP bind password to confirm: ");
176 bindPass = getpassphrase(prompt);
178 if (bindPass == NULL) {
179 (void) memset(bindPassword, 0, BUFSIZ);
180 return (PASSWD_UNMATCHED);
183 if (strcmp(bindPass, bindPassword) != 0) {
184 (void) memset(bindPassword, 0, BUFSIZ);
185 (void) memset(bindPass, 0, strlen(bindPass));
186 return (PASSWD_UNMATCHED);
187 } else {
188 (void) memset(bindPass, 0, strlen(bindPass));
189 if ((*ret_bindPass = (char *)malloc(strlen(bindPassword)+1))
190 == NULL) {
191 (void) memset(bindPassword, 0, BUFSIZ);
192 return (PROMPTGET_MEMORY_FAIL);
195 (void) strlcpy(*ret_bindPass, bindPassword,
196 strlen(bindPassword)+1);
198 /* Clean up and erase the credential info */
199 (void) memset(bindPassword, 0, BUFSIZ);
201 return (PROMPTGET_SUCCESS);
207 char *
208 switch_policy_str(struct __nsw_switchconfig *conf)
210 struct __nsw_lookup *look;
211 static char policy[256]; /* 256 is enough for (nis, files...etc) */
212 int previous = 0;
214 memset((char *)policy, 0, 256);
216 for (look = conf->lookups; look; look = look->next) {
217 if (previous)
218 strcat(policy, " ");
219 strcat(policy, look->service_name);
220 previous = 1;
222 return (policy);
226 no_switch_policy(struct __nsw_switchconfig *conf)
228 return (conf == NULL || conf->lookups == NULL);
232 is_switch_policy(struct __nsw_switchconfig *conf, char *target)
234 return (conf &&
235 conf->lookups &&
236 strcmp(conf->lookups->service_name, target) == 0 &&
237 conf->lookups->next == NULL);
240 char *
241 first_and_only_switch_policy(char *policy,
242 struct __nsw_switchconfig *default_conf,
243 char *head_msg)
245 struct __nsw_switchconfig *conf;
246 enum __nsw_parse_err perr;
247 int policy_correct = 1;
248 char *target_service = 0;
249 int use_default = 0;
251 if (default_conf == 0)
252 default_conf = &publickey_default;
254 conf = __nsw_getconfig(policy, &perr);
255 if (no_switch_policy(conf)) {
256 use_default = 1;
257 conf = default_conf;
260 target_service = conf->lookups->service_name;
262 if (conf->lookups->next != NULL) {
263 policy_correct = 0;
264 if (use_default) {
265 (void) fprintf(stderr,
266 "\n%s\n There is no publickey entry in %s.\n",
267 head_msg, __NSW_CONFIG_FILE);
268 (void) fprintf(stderr,
269 "The default publickey policy is \"publickey: %s\".\n",
270 switch_policy_str(default_conf));
271 } else
272 (void) fprintf(stderr,
273 "\n%s\nThe publickey entry in %s is \"publickey: %s\".\n",
274 head_msg, __NSW_CONFIG_FILE,
275 switch_policy_str(conf));
278 if (policy_correct == 0)
279 (void) fprintf(stderr,
280 "I cannot figure out which publickey database you want to update.\n");
281 if (!use_default && conf)
282 __nsw_freeconfig(conf);
284 if (policy_correct)
285 return (target_service);
286 else
287 return (0);
293 check_switch_policy(char *policy, char *target_service,
294 struct __nsw_switchconfig *default_conf,
295 char *head_msg, char *tail_msg)
297 struct __nsw_switchconfig *conf;
298 enum __nsw_parse_err perr;
299 int policy_correct = 1;
301 if (default_conf == 0)
302 default_conf = &publickey_default;
304 conf = __nsw_getconfig(policy, &perr);
305 if (no_switch_policy(conf)) {
306 if (!is_switch_policy(default_conf, target_service)) {
307 (void) fprintf(stderr,
308 "\n%s\nThere is no publickey entry in %s.\n",
309 head_msg, __NSW_CONFIG_FILE);
310 (void) fprintf(stderr,
311 "The default publickey policy is \"publickey: %s\".\n",
312 switch_policy_str(default_conf));
313 policy_correct = 0;
315 } else if (!is_switch_policy(conf, target_service)) {
316 (void) fprintf(stderr,
317 "\n%s\nThe publickey entry in %s is \"publickey: %s\".\n",
318 head_msg, __NSW_CONFIG_FILE,
319 switch_policy_str(conf));
320 policy_correct = 0;
322 /* should we exit ? */
323 if (policy_correct == 0)
324 (void) fprintf(stderr,
325 "It should be \"publickey: %s\"%s\n\n",
326 target_service, tail_msg);
327 if (conf)
328 __nsw_freeconfig(conf);
330 return (policy_correct);
334 get_pk_source(char *pk_service)
336 int db = 0, got_from_switch = 0;
338 /* No service specified, try to figure out from switch */
339 if (pk_service == 0) {
340 pk_service = first_and_only_switch_policy("publickey", 0,
341 "ERROR:");
342 if (pk_service == 0)
343 return (0);
344 (void) fprintf(stdout,
345 "Updating %s publickey database.\n",
346 pk_service);
347 got_from_switch = 1;
350 if (strcmp(pk_service, "ldap") == 0)
351 db = PK_LDAP;
352 else if (strcmp(pk_service, "nis") == 0)
353 db = PK_YP;
354 else if (strcmp(pk_service, "files") == 0)
355 db = PK_FILES;
356 else return (0);
359 * If we didn't get service name from switch, check switch
360 * and print warning about it source of publickeys if not unique
362 if (got_from_switch == 0)
363 check_switch_policy("publickey", pk_service, 0, "WARNING:",
364 db == PK_FILES ? "" :
365 "; add 'files' if you want the 'nobody' key.");
368 return (db); /* all passed */
372 /* ***************************** keylogin stuff *************************** */
374 keylogin(char *netname, char *secret)
376 struct key_netstarg netst;
378 netst.st_pub_key[0] = 0;
379 memcpy(netst.st_priv_key, secret, HEXKEYBYTES);
380 netst.st_netname = netname;
382 #ifdef NFS_AUTH
383 nra.authtype = AUTH_DES; /* only revoke DES creds */
384 nra.uid = getuid(); /* use the real uid */
385 if (_nfssys(NFS_REVAUTH, &nra) < 0) {
386 perror("Warning: NFS credentials not destroyed");
387 err = 1;
389 #endif
392 /* do actual key login */
393 if (key_setnet(&netst) < 0) {
394 (void) fprintf(stderr,
395 "Could not set %s's secret key\n", netname);
396 (void) fprintf(stderr, "May be the keyserv is down?\n");
397 return (0);
400 return (1);
403 nis_object *
404 init_entry()
406 static nis_object obj;
407 static entry_col cred_data[10];
408 entry_obj *eo;
410 memset((char *)(&obj), 0, sizeof (obj));
411 memset((char *)(cred_data), 0, sizeof (entry_col) * 10);
413 obj.zo_name = "cred";
414 obj.zo_group = "";
415 obj.zo_ttl = 43200;
416 obj.zo_data.zo_type = NIS_ENTRY_OBJ;
417 eo = &(obj.EN_data);
418 eo->en_type = "cred_tbl";
419 eo->en_cols.en_cols_val = cred_data;
420 eo->en_cols.en_cols_len = 5;
421 cred_data[4].ec_flags |= EN_CRYPT;
422 return (&obj);
426 static char *attrFilter[] = {
427 "objectclass",
428 "nispublickey",
429 "nissecretkey",
430 (char *)NULL
434 /* Determines if there is a NisKeyObject objectclass in a given entry */
435 static int
436 ldap_keyobj_exist(ns_ldap_entry_t *entry)
438 char **fattrs;
440 fattrs = __ns_ldap_getAttr(entry, "objectClass");
442 if (fattrs == NULL)
443 return (1);
445 while (*fattrs) {
446 if (strcasecmp("NisKeyObject", *fattrs) == 0)
447 return (1);
448 fattrs++;
451 return (0);
455 static char *keyAttrs[] = {
456 "nispublickey",
457 "nissecretkey",
458 NULL
462 * Replace or append new attribute value(s) to an attribute.
463 * Don't care about memory leaks, because program is short running.
466 static int
467 ldap_attr_mod(ns_ldap_entry_t *entry,
468 char *mechname,
469 char *public,
470 ns_ldap_attr_t **pkeyattrs,
471 char *crypt,
472 ns_ldap_attr_t **ckeyattrs)
474 char **alist[2];
475 char *keys[2];
477 char *mechfilter;
478 int mechfilterlen;
479 int q = 0;
480 int i, j;
481 int keycount[] = {0, 0};
482 ns_ldap_attr_t *attrs;
484 keys[0] = public;
485 keys[1] = crypt;
487 mechfilter = (char *)malloc(strlen(mechname) + 3);
488 if (mechfilter == NULL)
489 return (0);
490 sprintf(mechfilter, "{%s}", mechname);
491 mechfilterlen = strlen(mechfilter);
493 for (q = 0; keyAttrs[q] != NULL; q++) {
494 int found = 0;
496 for (i = 0; i < entry->attr_count; i++) {
497 int rep = 0;
498 ns_ldap_attr_t *attr = entry->attr_pair[i];
499 char *name = attr->attrname;
500 int count = 0;
502 if (strcasecmp(keyAttrs[q], name) == 0) {
503 found++;
504 count = attr->value_count;
505 alist[q] = (char **)malloc(sizeof (char *) * (count + 1));
506 if (alist[q] == NULL)
507 return (0);
508 alist[q][attr->value_count] = NULL;
509 for (j = 0; j < attr->value_count; j++) {
510 char *val = attr->attrvalue[j];
511 if (strncasecmp(val, mechfilter,
512 mechfilterlen) == 0) {
513 /* Replace entry */
514 rep++;
515 alist[q][j] = keys[q];
516 } else
517 alist[q][j] = val;
518 ++keycount[q];
520 if (!rep) {
521 /* Add entry to list */
522 alist[q] = (char **)realloc(alist[q],
523 sizeof (char *) * (count + 2));
524 if (alist[q] == NULL)
525 return (0);
526 alist[q][attr->value_count + 1] = NULL;
527 alist[q][attr->value_count] = keys[q];
528 ++keycount[q];
532 if (!found) {
533 /* Attribute does not exist, add entry anyways */
534 alist[q] = (char **)malloc(sizeof (char *) * 2);
535 if (alist[q] == NULL)
536 return (0);
537 alist[q][0] = keys[q];
538 alist[q][1] = NULL;
539 ++keycount[q];
542 if ((attrs = (ns_ldap_attr_t *)calloc(1,
543 sizeof (ns_ldap_attr_t))) == NULL)
544 return (0);
545 attrs->attrname = "nisPublicKey";
546 attrs->attrvalue = alist[0];
547 attrs->value_count = keycount[0];
548 *pkeyattrs = attrs;
550 if ((attrs = (ns_ldap_attr_t *)calloc(1,
551 sizeof (ns_ldap_attr_t))) == NULL)
552 return (0);
553 attrs->attrname = "nisSecretKey";
554 attrs->attrvalue = alist[1];
555 attrs->value_count = keycount[1];
556 *ckeyattrs = attrs;
557 return (1);
562 * Do the actual Add or update of attributes in attrs.
563 * The parameter 'update4host' is a flag that tells the function which
564 * DN and password should be used to bind to ldap. If it is an update
565 * for a host (update4host > 0), the two parameters "bindDN" and
566 * "bindPasswd" would be used to bind as the directory manager,
567 * otherwise "dn" and "passwd" would be used to bind as an individual
568 * user.
570 static void
571 update_ldap_attr(const char *dn,
572 ns_ldap_attr_t **attrs,
573 const char *passwd,
574 int add,
575 int update4host,
576 const char *bindDN,
577 const char *bindPasswd)
579 int ldaprc;
580 int authstried = 0;
581 char *msg;
582 char *ldap_pw;
583 char **certpath = NULL;
584 ns_auth_t **app;
585 ns_auth_t **authpp = NULL;
586 ns_auth_t *authp = NULL;
587 ns_cred_t *credp;
588 ns_ldap_error_t *errorp = NULL;
589 int status;
591 if ((credp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t))) == NULL) {
592 fprintf(stderr, "Can not allocate cred buffer.\n");
593 goto out;
597 * if this is an update for host, use the bindDN from the
598 * command prompt, otherwise use user's DN directly.
600 if (update4host)
601 credp->cred.unix_cred.userID = strdup(bindDN);
602 else
603 credp->cred.unix_cred.userID = strdup(dn);
605 if (credp->cred.unix_cred.userID == NULL) {
606 fprintf(stderr, "Memory allocation failure (userID)\n");
607 goto out;
610 if (update4host) {
611 credp->cred.unix_cred.passwd = strdup(bindPasswd);
612 } else {
613 if (passwd)
614 credp->cred.unix_cred.passwd = strdup(passwd);
615 else {
616 /* Make sure a valid password is received. */
617 status = get_ldap_bindPassword(&ldap_pw);
619 if (status != PROMPTGET_SUCCESS) {
620 if (!ldap_pw)
621 free(ldap_pw);
622 goto out;
624 credp->cred.unix_cred.passwd = ldap_pw;
628 if (credp->cred.unix_cred.passwd == NULL) {
629 fprintf(stderr, "Memory allocation failure (passwd)\n");
630 goto out;
633 /* get host certificate path, if one is configured */
634 if (__ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P,
635 (void ***)&certpath, &errorp) != NS_LDAP_SUCCESS)
636 goto out;
638 if (certpath && *certpath)
639 credp->hostcertpath = *certpath;
641 /* Load the service specific authentication method */
642 if (__ns_ldap_getServiceAuthMethods("keyserv", &authpp, &errorp) !=
643 NS_LDAP_SUCCESS)
644 goto out;
647 * if authpp is null, there is no serviceAuthenticationMethod
648 * try default authenticationMethod
650 if (authpp == NULL) {
651 if (__ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp,
652 &errorp) != NS_LDAP_SUCCESS)
653 goto out;
657 * if authpp is still null, then can not authenticate, log
658 * error message and return error
660 if (authpp == NULL) {
661 fprintf(stderr, "No LDAP authentication method configured.\n"
662 " configured.\n");
663 goto out;
667 * Walk the array and try all authentication methods in order except
668 * for "none".
670 for (app = authpp; *app; app++) {
671 authp = *app;
672 /* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */
673 if (authp->type == NS_LDAP_AUTH_NONE)
674 continue;
675 authstried++;
676 credp->auth.type = authp->type;
677 credp->auth.tlstype = authp->tlstype;
678 credp->auth.saslmech = authp->saslmech;
679 credp->auth.saslopt = authp->saslopt;
681 if (add == TRUE)
682 ldaprc = __ns_ldap_addAttr("publickey", dn,
683 (const ns_ldap_attr_t * const *)attrs,
684 credp, NULL, &errorp);
685 else
686 ldaprc = __ns_ldap_repAttr("publickey", dn,
687 (const ns_ldap_attr_t * const *)attrs,
688 credp, NULL, &errorp);
689 if (ldaprc == NS_LDAP_SUCCESS) {
690 /* clean up ns_cred_t structure in memory */
691 if (credp != NULL)
692 (void) __ns_ldap_freeCred(&credp);
693 return;
696 /* XXX add checking for cases of authentication errors */
697 if ((ldaprc == NS_LDAP_INTERNAL) &&
698 ((errorp->status == LDAP_INAPPROPRIATE_AUTH) ||
699 (errorp->status == LDAP_INVALID_CREDENTIALS))) {
700 fprintf(stderr, "LDAP authentication failed.\n");
701 goto out;
704 if (authstried == 0)
705 fprintf(stderr, "No legal authentication method configured.\n");
707 out:
708 /* clean up ns_cred_t structure in memory */
709 if (credp != NULL) {
710 (void) __ns_ldap_freeCred(&credp);
713 if (errorp) {
714 __ns_ldap_err2str(errorp->status, &msg);
715 fprintf(stderr, "LDAP error: %s.\n", msg);
717 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
718 exit(1);
723 * Update LDAP nisplublickey entry with new key information via SLDAP.
724 * Free and clean up memory that stores credential data soon after
725 * they are not used or an error comes up.
728 ldap_update(char *mechname,
729 char *netname,
730 char *public,
731 char *crypt,
732 char *passwd)
734 char *netnamecpy;
735 char *id;
736 char *domain;
737 char *dn;
738 char *db;
739 char *filter;
740 ns_ldap_error_t *errorp;
741 char *pkeyatval, *ckeyatval;
742 ns_ldap_result_t *res;
743 ns_ldap_attr_t *pattrs, *cattrs;
744 int update4host = FALSE;
745 char *bindDN = NULL;
746 char *bindPasswd = NULL;
747 int status;
749 /* Generate DN */
750 if ((netnamecpy = strdup(netname)) == NULL)
751 return (0);
752 if (((id = strchr(netnamecpy, '.')) == NULL) ||
753 ((domain = strchr(netnamecpy, '@')) == NULL))
754 return (0);
755 else {
756 *domain++ = '\0';
757 *id++ = '\0';
759 id = strdup(id);
760 if (id == NULL) {
761 free(netnamecpy);
762 fprintf(stderr, "LDAP memory error (id)\n");
763 return (0);
765 domain = strdup(domain);
766 if (domain == NULL) {
767 free(netnamecpy);
768 free(id);
769 fprintf(stderr, "LDAP memory error (domain)\n");
770 return (0);
772 free(netnamecpy);
775 if (isdigit(*id)) {
776 /* We be user. */
777 __ns_ldap_uid2dn(id, &dn, NULL, &errorp);
778 if (dn == NULL) {
779 fprintf(stderr, "Could not obtain LDAP dn\n");
780 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
781 program_name);
782 exit(1);
784 db = "passwd";
785 filter = (char *)malloc(strlen(id) + 13);
786 if (filter)
787 sprintf(filter, "(uidnumber=%s)", id);
788 else {
789 fprintf(stderr, "Can not allocate filter buffer.\n");
790 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
791 program_name);
792 exit(1);
794 } else {
795 /* We be host. */
796 update4host = TRUE;
798 __ns_ldap_host2dn(id, NULL, &dn, NULL, &errorp);
799 if (dn == NULL) {
800 fprintf(stderr, "Could not obtain LDAP dn\n");
801 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
802 program_name);
803 exit(1);
806 db = "hosts";
807 filter = (char *)malloc(strlen(id) + 6);
808 if (filter)
809 sprintf(filter, "(cn=%s)", id);
810 else {
811 fprintf(stderr, "Can not allocate filter buffer.\n");
812 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
813 program_name);
814 exit(1);
817 /* Prompt for ldap bind DN for entry udpates */
818 status = get_ldap_bindDN(&bindDN);
820 if (status != PROMPTGET_SUCCESS) {
821 FREE_CREDINFO(bindDN);
822 fprintf(stderr,
823 "Failed to get a valid LDAP bind DN.\n"
824 "%s: key-pair(s) unchanged.\n",
825 program_name);
826 exit(1);
829 /* Prompt for ldap bind password */
830 status = get_ldap_bindPassword(&bindPasswd);
832 if (status != PROMPTGET_SUCCESS) {
833 FREE_CREDINFO(bindPasswd);
834 FREE_CREDINFO(bindDN);
836 fprintf(stderr,
837 "Failed to get a valid LDAP bind password."
838 "\n%s: key-pair(s) unchanged.\n",
839 program_name);
840 exit(1);
844 /* Construct attribute values */
845 pkeyatval = (char *)malloc(strlen(mechname) + strlen(public) + 3);
846 if (pkeyatval == NULL) {
847 FREE_CREDINFO(bindPasswd);
848 FREE_CREDINFO(bindDN);
849 fprintf(stderr, "LDAP memory error (pkeyatval)\n");
850 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
851 exit(1);
853 sprintf(pkeyatval, "{%s}%s", mechname, public);
854 ckeyatval = (char *)malloc(strlen(mechname) + strlen(crypt) + 3);
855 if (ckeyatval == NULL) {
856 FREE_CREDINFO(pkeyatval);
857 FREE_CREDINFO(bindPasswd);
858 FREE_CREDINFO(bindDN);
859 fprintf(stderr, "LDAP memory error (pkeyatval)\n");
860 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
861 exit(1);
863 sprintf(ckeyatval, "{%s}%s", mechname, crypt);
865 /* Does entry exist? */
866 if ((__ns_ldap_list(db, filter, NULL, (const char **)attrFilter,
867 NULL, 0, &res, &errorp,
868 NULL, NULL) == NS_LDAP_SUCCESS) && res == NULL) {
869 FREE_CREDINFO(ckeyatval);
870 FREE_CREDINFO(pkeyatval);
871 FREE_CREDINFO(bindPasswd);
872 FREE_CREDINFO(bindDN);
873 fprintf(stderr, "LDAP entry does not exist.\n");
874 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
875 exit(1);
878 /* Entry exists, modify attributes for public and secret keys */
880 /* Is there a NisKeyObject in entry? */
881 if (!ldap_keyobj_exist(&res->entry[0])) {
882 /* Add NisKeyObject objectclass and the keys */
883 char **newattr;
884 ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */
886 /* set objectclass */
887 newattr = (char **)calloc(2, sizeof (char *));
888 newattr[0] = "NisKeyObject";
889 newattr[1] = NULL;
890 if ((attrs[0] = (ns_ldap_attr_t *)calloc(1,
891 sizeof (ns_ldap_attr_t))) == NULL) {
892 FREE_CREDINFO(ckeyatval);
893 FREE_CREDINFO(pkeyatval);
894 FREE_CREDINFO(bindPasswd);
895 FREE_CREDINFO(bindDN);
896 fprintf(stderr, "Memory allocation failed\n");
897 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
898 program_name);
899 exit(1);
901 attrs[0]->attrname = "objectClass";
902 attrs[0]->attrvalue = newattr;
903 attrs[0]->value_count = 1;
905 /* set publickey */
906 newattr = (char **)calloc(2, sizeof (char *));
907 newattr[0] = pkeyatval;
908 newattr[1] = NULL;
909 if ((attrs[1] = (ns_ldap_attr_t *)calloc(1,
910 sizeof (ns_ldap_attr_t))) == NULL) {
911 FREE_CREDINFO(ckeyatval);
912 FREE_CREDINFO(pkeyatval);
913 FREE_CREDINFO(bindPasswd);
914 FREE_CREDINFO(bindDN);
915 fprintf(stderr, "Memory allocation failed\n");
916 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
917 program_name);
918 exit(1);
920 attrs[1]->attrname = "nisPublicKey";
921 attrs[1]->attrvalue = newattr;
922 attrs[1]->value_count = 1;
924 /* set privatekey */
925 newattr = (char **)calloc(2, sizeof (char *));
926 newattr[0] = ckeyatval;
927 newattr[1] = NULL;
928 if ((attrs[2] = (ns_ldap_attr_t *)calloc(1,
929 sizeof (ns_ldap_attr_t))) == NULL) {
930 FREE_CREDINFO(ckeyatval);
931 FREE_CREDINFO(pkeyatval);
932 FREE_CREDINFO(bindPasswd);
933 FREE_CREDINFO(bindDN);
934 fprintf(stderr, "Memory allocation failed\n");
935 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
936 program_name);
937 exit(1);
939 attrs[2]->attrname = "nisSecretKey";
940 attrs[2]->attrvalue = newattr;
941 attrs[2]->value_count = 1;
943 /* terminator */
944 attrs[3] = NULL;
946 update_ldap_attr(dn, attrs, passwd, TRUE, update4host,
947 bindDN, bindPasswd);
948 } else {
949 /* object class already exists, replace keys */
950 ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */
952 if (!ldap_attr_mod(&res->entry[0], mechname,
953 pkeyatval, &pattrs,
954 ckeyatval, &cattrs)) {
955 FREE_CREDINFO(ckeyatval);
956 FREE_CREDINFO(pkeyatval);
957 FREE_CREDINFO(bindPasswd);
958 FREE_CREDINFO(bindDN);
959 fprintf(stderr,
960 "Could not generate LDAP attribute list.\n");
961 fprintf(stderr,
962 "%s: key-pair(s) unchanged.\n", program_name);
963 exit(1);
966 attrs[0] = pattrs;
967 attrs[1] = cattrs;
968 attrs[2] = NULL;
970 update_ldap_attr(dn, attrs, passwd, FALSE, update4host,
971 bindDN, bindPasswd);
974 FREE_CREDINFO(ckeyatval);
975 FREE_CREDINFO(pkeyatval);
976 FREE_CREDINFO(bindPasswd);
977 FREE_CREDINFO(bindDN);
979 return (0);