1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
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>
38
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";
44
45 #define ROOTKEY_FILE "/etc/.rootkey"
46
47 #ifndef MAXHOSTNAMELEN
48 #define MAXHOSTNAMELEN 256
49 #endif
50
51 #define PK_FILES 1
52 #define PK_YP 2
53 #define PK_LDAP 4
54
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
60
61 #define FREE_CREDINFO(s) \
62 if ((s)) { (void) memset((s), 0, strlen((s))); }
63
64
65 /* ************************ switch functions *************************** */
66
67 /* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */
68 #define DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE}
69
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};
74
75 static int get_ldap_bindDN(char **);
76 static int get_ldap_bindPassword(char **);
77
78 /*
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.
82 */
83 static int
get_ldap_bindDN(char ** ret_bindDN)84 get_ldap_bindDN(char **ret_bindDN)
85 {
86
87 char bindDN[BUFSIZ];
88 char prompt[BUFSIZ];
89 int blen, pos;
90
91 /* set the initial value for bindDN buffer */
92 (void) memset(bindDN, 0, BUFSIZ);
93
94 (void) snprintf(prompt, BUFSIZ,
95 "\nThe LDAP bind DN and password are required for this update.\n"
96 "If you are not sure what values to enter, please contact your\n"
97 "LDAP administrator.\n\nPlease enter LDAP bind DN [%s]: ",
98 LDAP_BINDDN_DEFAULT);
99
100 printf(prompt);
101
102 if (fgets(bindDN, sizeof (bindDN), stdin) == NULL) {
103 (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ);
104 }
105
106 blen = strlen(bindDN);
107
108 /* Check if the buffer ends with a newline */
109 if ((blen > 0) && (bindDN[blen - 1] == '\n')) {
110 bindDN[blen - 1] = '\0';
111 blen -= 1;
112 }
113
114 /* Remove the white spaces */
115 if (blen > 0) {
116 for (pos = blen - 1; pos >= 0; pos--) {
117 if (isspace(bindDN[pos]))
118 bindDN[pos] = '\0';
119 else
120 break;
121 }
122 }
123
124 /* Use the default bindDN, if the buffer contains no characters */
125 if (strlen(bindDN) == 0)
126 (void) strlcpy(bindDN, LDAP_BINDDN_DEFAULT, BUFSIZ);
127
128 if ((*ret_bindDN = (char *)malloc(strlen(bindDN)+1)) == NULL) {
129 (void) memset(bindDN, 0, BUFSIZ);
130 return (PROMPTGET_MEMORY_FAIL);
131 }
132
133 (void) strlcpy(*ret_bindDN, bindDN, strlen(bindDN)+1);
134
135 /* Clean up and erase the credential info */
136 (void) memset(bindDN, 0, BUFSIZ);
137
138 return (PROMPTGET_SUCCESS);
139 }
140
141
142 /*
143 * Prompt the user for a ldap bind password.
144 */
145 static int
get_ldap_bindPassword(char ** ret_bindPass)146 get_ldap_bindPassword(char **ret_bindPass)
147 {
148
149 char bindPassword[BUFSIZ];
150 char prompt[BUFSIZ];
151 char *bindPass = NULL;
152
153 /* set the initial value for bindPassword buffer */
154 (void) memset(bindPassword, 0, BUFSIZ);
155 *ret_bindPass = NULL;
156
157 (void) snprintf(prompt, BUFSIZ,
158 "Please enter LDAP bind password: ");
159
160 bindPass = getpassphrase(prompt);
161
162 if (bindPass == NULL)
163 return (PROMPTGET_FAIL);
164
165 (void) strlcpy(bindPassword, bindPass, BUFSIZ);
166
167 /* clean the static buffer returned from getpassphrase call */
168 (void) memset(bindPass, 0, strlen(bindPass));
169 bindPass = NULL;
170
171 /*
172 * Re-enter the bind passowrd and compare it with the one
173 * from previous entered.
174 */
175 (void) snprintf(prompt, BUFSIZ,
176 "Re-enter LDAP bind password to confirm: ");
177
178 bindPass = getpassphrase(prompt);
179
180 if (bindPass == NULL) {
181 (void) memset(bindPassword, 0, BUFSIZ);
182 return (PASSWD_UNMATCHED);
183 }
184
185 if (strcmp(bindPass, bindPassword) != 0) {
186 (void) memset(bindPassword, 0, BUFSIZ);
187 (void) memset(bindPass, 0, strlen(bindPass));
188 return (PASSWD_UNMATCHED);
189 } else {
190 (void) memset(bindPass, 0, strlen(bindPass));
191 if ((*ret_bindPass = (char *)malloc(strlen(bindPassword)+1))
192 == NULL) {
193 (void) memset(bindPassword, 0, BUFSIZ);
194 return (PROMPTGET_MEMORY_FAIL);
195 }
196
197 (void) strlcpy(*ret_bindPass, bindPassword,
198 strlen(bindPassword)+1);
199
200 /* Clean up and erase the credential info */
201 (void) memset(bindPassword, 0, BUFSIZ);
202
203 return (PROMPTGET_SUCCESS);
204 }
205 }
206
207
208
209 char *
switch_policy_str(struct __nsw_switchconfig * conf)210 switch_policy_str(struct __nsw_switchconfig *conf)
211 {
212 struct __nsw_lookup *look;
213 static char policy[256]; /* 256 is enough for (nis, files...etc) */
214 int previous = 0;
215
216 memset((char *)policy, 0, 256);
217
218 for (look = conf->lookups; look; look = look->next) {
219 if (previous)
220 strcat(policy, " ");
221 strcat(policy, look->service_name);
222 previous = 1;
223 }
224 return (policy);
225 }
226
227 int
no_switch_policy(struct __nsw_switchconfig * conf)228 no_switch_policy(struct __nsw_switchconfig *conf)
229 {
230 return (conf == NULL || conf->lookups == NULL);
231 }
232
233 int
is_switch_policy(struct __nsw_switchconfig * conf,char * target)234 is_switch_policy(struct __nsw_switchconfig *conf, char *target)
235 {
236 return (conf &&
237 conf->lookups &&
238 strcmp(conf->lookups->service_name, target) == 0 &&
239 conf->lookups->next == NULL);
240 }
241
242 char *
first_and_only_switch_policy(char * policy,struct __nsw_switchconfig * default_conf,char * head_msg)243 first_and_only_switch_policy(char *policy,
244 struct __nsw_switchconfig *default_conf, char *head_msg)
245 {
246 struct __nsw_switchconfig *conf;
247 enum __nsw_parse_err perr;
248 int policy_correct = 1;
249 char *target_service = 0;
250 int use_default = 0;
251
252 if (default_conf == 0)
253 default_conf = &publickey_default;
254
255 conf = __nsw_getconfig(policy, &perr);
256 if (no_switch_policy(conf)) {
257 use_default = 1;
258 conf = default_conf;
259 }
260
261 target_service = conf->lookups->service_name;
262
263 if (conf->lookups->next != NULL) {
264 policy_correct = 0;
265 if (use_default) {
266 (void) fprintf(stderr,
267 "\n%s\n There is no publickey entry in %s.\n",
268 head_msg, __NSW_CONFIG_FILE);
269 (void) fprintf(stderr,
270 "The default publickey policy is \"publickey: %s\".\n",
271 switch_policy_str(default_conf));
272 } else
273 (void) fprintf(stderr,
274 "\n%s\nThe publickey entry in %s is \"publickey: %s\".\n",
275 head_msg, __NSW_CONFIG_FILE,
276 switch_policy_str(conf));
277 }
278
279 if (policy_correct == 0)
280 (void) fprintf(stderr,
281 "I cannot figure out which publickey database you want to update.\n");
282 if (!use_default && conf)
283 __nsw_freeconfig(conf);
284
285 if (policy_correct)
286 return (target_service);
287 else
288 return (0);
289 }
290
291
292
293 int
check_switch_policy(char * policy,char * target_service,struct __nsw_switchconfig * default_conf,char * head_msg,char * tail_msg)294 check_switch_policy(char *policy, char *target_service,
295 struct __nsw_switchconfig *default_conf, char *head_msg, char *tail_msg)
296 {
297 struct __nsw_switchconfig *conf;
298 enum __nsw_parse_err perr;
299 int policy_correct = 1;
300
301 if (default_conf == 0)
302 default_conf = &publickey_default;
303
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;
314 }
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;
321 }
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);
329
330 return (policy_correct);
331 }
332
333 int
get_pk_source(char * pk_service)334 get_pk_source(char *pk_service)
335 {
336 int db = 0, got_from_switch = 0;
337
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;
348 }
349
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);
357
358 /*
359 * If we didn't get service name from switch, check switch
360 * and print warning about it source of publickeys if not unique
361 */
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.");
366
367
368 return (db); /* all passed */
369 }
370
371
372 /* ***************************** keylogin stuff *************************** */
373 int
keylogin(char * netname,char * secret)374 keylogin(char *netname, char *secret)
375 {
376 struct key_netstarg netst;
377
378 netst.st_pub_key[0] = 0;
379 memcpy(netst.st_priv_key, secret, HEXKEYBYTES);
380 netst.st_netname = netname;
381
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;
388 }
389 #endif
390
391
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);
398 }
399
400 return (1);
401 }
402
403 nis_object *
init_entry()404 init_entry()
405 {
406 static nis_object obj;
407 static entry_col cred_data[10];
408 entry_obj *eo;
409
410 memset((char *)(&obj), 0, sizeof (obj));
411 memset((char *)(cred_data), 0, sizeof (entry_col) * 10);
412
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);
423 }
424
425
426 static char *attrFilter[] = {
427 "objectclass",
428 "nispublickey",
429 "nissecretkey",
430 (char *)NULL
431 };
432
433
434 /* Determines if there is a NisKeyObject objectclass in a given entry */
435 static int
ldap_keyobj_exist(ns_ldap_entry_t * entry)436 ldap_keyobj_exist(ns_ldap_entry_t *entry)
437 {
438 char **fattrs;
439
440 fattrs = __ns_ldap_getAttr(entry, "objectClass");
441
442 if (fattrs == NULL)
443 return (1);
444
445 while (*fattrs) {
446 if (strcasecmp("NisKeyObject", *fattrs) == 0)
447 return (1);
448 fattrs++;
449 }
450
451 return (0);
452 }
453
454
455 static char *keyAttrs[] = {
456 "nispublickey",
457 "nissecretkey",
458 NULL
459 };
460
461 /*
462 * Replace or append new attribute value(s) to an attribute.
463 * Don't care about memory leaks, because program is short running.
464 */
465
466 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)467 ldap_attr_mod(ns_ldap_entry_t *entry, char *mechname, char *public,
468 ns_ldap_attr_t **pkeyattrs, char *crypt, ns_ldap_attr_t **ckeyattrs)
469 {
470 char **alist[2];
471 char *keys[2];
472
473 char *mechfilter;
474 int mechfilterlen;
475 int q = 0;
476 int i, j;
477 int keycount[] = {0, 0};
478 ns_ldap_attr_t *attrs;
479
480 keys[0] = public;
481 keys[1] = crypt;
482
483 mechfilter = (char *)malloc(strlen(mechname) + 3);
484 if (mechfilter == NULL)
485 return (0);
486 sprintf(mechfilter, "{%s}", mechname);
487 mechfilterlen = strlen(mechfilter);
488
489 for (q = 0; keyAttrs[q] != NULL; q++) {
490 int found = 0;
491
492 for (i = 0; i < entry->attr_count; i++) {
493 int rep = 0;
494 ns_ldap_attr_t *attr = entry->attr_pair[i];
495 char *name = attr->attrname;
496 int count = 0;
497
498 if (strcasecmp(keyAttrs[q], name) == 0) {
499 found++;
500 count = attr->value_count;
501 alist[q] = (char **)malloc(sizeof (char *) * (count + 1));
502 if (alist[q] == NULL)
503 return (0);
504 alist[q][attr->value_count] = NULL;
505 for (j = 0; j < attr->value_count; j++) {
506 char *val = attr->attrvalue[j];
507 if (strncasecmp(val, mechfilter,
508 mechfilterlen) == 0) {
509 /* Replace entry */
510 rep++;
511 alist[q][j] = keys[q];
512 } else
513 alist[q][j] = val;
514 ++keycount[q];
515 }
516 if (!rep) {
517 /* Add entry to list */
518 alist[q] = (char **)realloc(alist[q],
519 sizeof (char *) * (count + 2));
520 if (alist[q] == NULL)
521 return (0);
522 alist[q][attr->value_count + 1] = NULL;
523 alist[q][attr->value_count] = keys[q];
524 ++keycount[q];
525 }
526 }
527 }
528 if (!found) {
529 /* Attribute does not exist, add entry anyways */
530 alist[q] = (char **)malloc(sizeof (char *) * 2);
531 if (alist[q] == NULL)
532 return (0);
533 alist[q][0] = keys[q];
534 alist[q][1] = NULL;
535 ++keycount[q];
536 }
537 }
538 if ((attrs = (ns_ldap_attr_t *)calloc(1,
539 sizeof (ns_ldap_attr_t))) == NULL)
540 return (0);
541 attrs->attrname = "nisPublicKey";
542 attrs->attrvalue = alist[0];
543 attrs->value_count = keycount[0];
544 *pkeyattrs = attrs;
545
546 if ((attrs = (ns_ldap_attr_t *)calloc(1,
547 sizeof (ns_ldap_attr_t))) == NULL)
548 return (0);
549 attrs->attrname = "nisSecretKey";
550 attrs->attrvalue = alist[1];
551 attrs->value_count = keycount[1];
552 *ckeyattrs = attrs;
553 return (1);
554 }
555
556
557 /*
558 * Do the actual Add or update of attributes in attrs.
559 * The parameter 'update4host' is a flag that tells the function which
560 * DN and password should be used to bind to ldap. If it is an update
561 * for a host (update4host > 0), the two parameters "bindDN" and
562 * "bindPasswd" would be used to bind as the directory manager,
563 * otherwise "dn" and "passwd" would be used to bind as an individual
564 * user.
565 */
566 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)567 update_ldap_attr(const char *dn, ns_ldap_attr_t **attrs, const char *passwd,
568 int add, int update4host, const char *bindDN, const char *bindPasswd)
569 {
570 int ldaprc;
571 int authstried = 0;
572 char *msg;
573 char *ldap_pw;
574 char **certpath = NULL;
575 ns_auth_t **app;
576 ns_auth_t **authpp = NULL;
577 ns_auth_t *authp = NULL;
578 ns_cred_t *credp;
579 ns_ldap_error_t *errorp = NULL;
580 int status;
581
582 if ((credp = (ns_cred_t *)calloc(1, sizeof (ns_cred_t))) == NULL) {
583 fprintf(stderr, "Can not allocate cred buffer.\n");
584 goto out;
585 }
586
587 /*
588 * if this is an update for host, use the bindDN from the
589 * command prompt, otherwise use user's DN directly.
590 */
591 if (update4host)
592 credp->cred.unix_cred.userID = strdup(bindDN);
593 else
594 credp->cred.unix_cred.userID = strdup(dn);
595
596 if (credp->cred.unix_cred.userID == NULL) {
597 fprintf(stderr, "Memory allocation failure (userID)\n");
598 goto out;
599 }
600
601 if (update4host) {
602 credp->cred.unix_cred.passwd = strdup(bindPasswd);
603 } else {
604 if (passwd)
605 credp->cred.unix_cred.passwd = strdup(passwd);
606 else {
607 /* Make sure a valid password is received. */
608 status = get_ldap_bindPassword(&ldap_pw);
609
610 if (status != PROMPTGET_SUCCESS) {
611 if (!ldap_pw)
612 free(ldap_pw);
613 goto out;
614 }
615 credp->cred.unix_cred.passwd = ldap_pw;
616 }
617 }
618
619 if (credp->cred.unix_cred.passwd == NULL) {
620 fprintf(stderr, "Memory allocation failure (passwd)\n");
621 goto out;
622 }
623
624 /* get host certificate path, if one is configured */
625 if (__ns_ldap_getParam(NS_LDAP_HOST_CERTPATH_P,
626 (void ***)&certpath, &errorp) != NS_LDAP_SUCCESS)
627 goto out;
628
629 if (certpath && *certpath)
630 credp->hostcertpath = *certpath;
631
632 /* Load the service specific authentication method */
633 if (__ns_ldap_getServiceAuthMethods("keyserv", &authpp, &errorp) !=
634 NS_LDAP_SUCCESS)
635 goto out;
636
637 /*
638 * if authpp is null, there is no serviceAuthenticationMethod
639 * try default authenticationMethod
640 */
641 if (authpp == NULL) {
642 if (__ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp,
643 &errorp) != NS_LDAP_SUCCESS)
644 goto out;
645 }
646
647 /*
648 * if authpp is still null, then can not authenticate, log
649 * error message and return error
650 */
651 if (authpp == NULL) {
652 fprintf(stderr, "No LDAP authentication method configured.\n"
653 " configured.\n");
654 goto out;
655 }
656
657 /*
658 * Walk the array and try all authentication methods in order except
659 * for "none".
660 */
661 for (app = authpp; *app; app++) {
662 authp = *app;
663 /* what about disabling other mechanisms? "tls:sasl/EXTERNAL" */
664 if (authp->type == NS_LDAP_AUTH_NONE)
665 continue;
666 authstried++;
667 credp->auth.type = authp->type;
668 credp->auth.tlstype = authp->tlstype;
669 credp->auth.saslmech = authp->saslmech;
670 credp->auth.saslopt = authp->saslopt;
671
672 if (add == TRUE)
673 ldaprc = __ns_ldap_addAttr("publickey", dn,
674 (const ns_ldap_attr_t * const *)attrs,
675 credp, 0, &errorp);
676 else
677 ldaprc = __ns_ldap_repAttr("publickey", dn,
678 (const ns_ldap_attr_t * const *)attrs,
679 credp, 0, &errorp);
680 if (ldaprc == NS_LDAP_SUCCESS) {
681 /* clean up ns_cred_t structure in memory */
682 if (credp != NULL)
683 (void) __ns_ldap_freeCred(&credp);
684 return;
685 }
686
687 /* XXX add checking for cases of authentication errors */
688 if ((ldaprc == NS_LDAP_INTERNAL) &&
689 ((errorp->status == LDAP_INAPPROPRIATE_AUTH) ||
690 (errorp->status == LDAP_INVALID_CREDENTIALS))) {
691 fprintf(stderr, "LDAP authentication failed.\n");
692 goto out;
693 }
694 }
695 if (authstried == 0)
696 fprintf(stderr, "No legal authentication method configured.\n");
697
698 out:
699 /* clean up ns_cred_t structure in memory */
700 if (credp != NULL) {
701 (void) __ns_ldap_freeCred(&credp);
702 }
703
704 if (errorp) {
705 __ns_ldap_err2str(errorp->status, &msg);
706 fprintf(stderr, "LDAP error: %s.\n", msg);
707 }
708 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
709 exit(1);
710 }
711
712
713 /*
714 * Update LDAP nisplublickey entry with new key information via SLDAP.
715 * Free and clean up memory that stores credential data soon after
716 * they are not used or an error comes up.
717 */
718 int
ldap_update(char * mechname,char * netname,char * public,char * crypt,char * passwd)719 ldap_update(char *mechname, char *netname, char *public, char *crypt,
720 char *passwd)
721 {
722 char *netnamecpy;
723 char *id;
724 char *domain;
725 char *dn;
726 char *db;
727 char *filter;
728 ns_ldap_error_t *errorp;
729 char *pkeyatval, *ckeyatval;
730 ns_ldap_result_t *res;
731 ns_ldap_attr_t *pattrs, *cattrs;
732 int update4host = FALSE;
733 char *bindDN = NULL;
734 char *bindPasswd = NULL;
735 int status;
736
737 /* Generate DN */
738 if ((netnamecpy = strdup(netname)) == NULL)
739 return (0);
740 if (((id = strchr(netnamecpy, '.')) == NULL) ||
741 ((domain = strchr(netnamecpy, '@')) == NULL))
742 return (0);
743 else {
744 *domain++ = '\0';
745 *id++ = '\0';
746
747 id = strdup(id);
748 if (id == NULL) {
749 free(netnamecpy);
750 fprintf(stderr, "LDAP memory error (id)\n");
751 return (0);
752 }
753 domain = strdup(domain);
754 if (domain == NULL) {
755 free(netnamecpy);
756 free(id);
757 fprintf(stderr, "LDAP memory error (domain)\n");
758 return (0);
759 }
760 free(netnamecpy);
761 }
762
763 if (isdigit(*id)) {
764 /* We be user. */
765 __ns_ldap_uid2dn(id, &dn, NULL, &errorp);
766 if (dn == NULL) {
767 fprintf(stderr, "Could not obtain LDAP dn\n");
768 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
769 program_name);
770 exit(1);
771 }
772 db = "passwd";
773 filter = (char *)malloc(strlen(id) + 13);
774 if (filter)
775 sprintf(filter, "(uidnumber=%s)", id);
776 else {
777 fprintf(stderr, "Can not allocate filter buffer.\n");
778 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
779 program_name);
780 exit(1);
781 }
782 } else {
783 /* We be host. */
784 update4host = TRUE;
785
786 __ns_ldap_host2dn(id, NULL, &dn, NULL, &errorp);
787 if (dn == NULL) {
788 fprintf(stderr, "Could not obtain LDAP dn\n");
789 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
790 program_name);
791 exit(1);
792 }
793
794 db = "hosts";
795 filter = (char *)malloc(strlen(id) + 6);
796 if (filter)
797 sprintf(filter, "(cn=%s)", id);
798 else {
799 fprintf(stderr, "Can not allocate filter buffer.\n");
800 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
801 program_name);
802 exit(1);
803 }
804
805 /* Prompt for ldap bind DN for entry udpates */
806 status = get_ldap_bindDN(&bindDN);
807
808 if (status != PROMPTGET_SUCCESS) {
809 FREE_CREDINFO(bindDN);
810 fprintf(stderr,
811 "Failed to get a valid LDAP bind DN.\n"
812 "%s: key-pair(s) unchanged.\n",
813 program_name);
814 exit(1);
815 }
816
817 /* Prompt for ldap bind password */
818 status = get_ldap_bindPassword(&bindPasswd);
819
820 if (status != PROMPTGET_SUCCESS) {
821 FREE_CREDINFO(bindPasswd);
822 FREE_CREDINFO(bindDN);
823
824 fprintf(stderr,
825 "Failed to get a valid LDAP bind password."
826 "\n%s: key-pair(s) unchanged.\n",
827 program_name);
828 exit(1);
829 }
830 }
831
832 /* Construct attribute values */
833 pkeyatval = (char *)malloc(strlen(mechname) + strlen(public) + 3);
834 if (pkeyatval == NULL) {
835 FREE_CREDINFO(bindPasswd);
836 FREE_CREDINFO(bindDN);
837 fprintf(stderr, "LDAP memory error (pkeyatval)\n");
838 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
839 exit(1);
840 }
841 sprintf(pkeyatval, "{%s}%s", mechname, public);
842 ckeyatval = (char *)malloc(strlen(mechname) + strlen(crypt) + 3);
843 if (ckeyatval == NULL) {
844 FREE_CREDINFO(pkeyatval);
845 FREE_CREDINFO(bindPasswd);
846 FREE_CREDINFO(bindDN);
847 fprintf(stderr, "LDAP memory error (pkeyatval)\n");
848 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
849 exit(1);
850 }
851 sprintf(ckeyatval, "{%s}%s", mechname, crypt);
852
853 /* Does entry exist? */
854 if ((__ns_ldap_list(db, filter, NULL, (const char **)attrFilter,
855 NULL, 0, &res, &errorp,
856 NULL, NULL) == NS_LDAP_SUCCESS) && res == NULL) {
857 FREE_CREDINFO(ckeyatval);
858 FREE_CREDINFO(pkeyatval);
859 FREE_CREDINFO(bindPasswd);
860 FREE_CREDINFO(bindDN);
861 fprintf(stderr, "LDAP entry does not exist.\n");
862 fprintf(stderr, "%s: key-pair(s) unchanged.\n", program_name);
863 exit(1);
864 }
865
866 /* Entry exists, modify attributes for public and secret keys */
867
868 /* Is there a NisKeyObject in entry? */
869 if (!ldap_keyobj_exist(&res->entry[0])) {
870 /* Add NisKeyObject objectclass and the keys */
871 char **newattr;
872 ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */
873
874 /* set objectclass */
875 newattr = (char **)calloc(2, sizeof (char *));
876 newattr[0] = "NisKeyObject";
877 newattr[1] = NULL;
878 if ((attrs[0] = (ns_ldap_attr_t *)calloc(1,
879 sizeof (ns_ldap_attr_t))) == NULL) {
880 FREE_CREDINFO(ckeyatval);
881 FREE_CREDINFO(pkeyatval);
882 FREE_CREDINFO(bindPasswd);
883 FREE_CREDINFO(bindDN);
884 fprintf(stderr, "Memory allocation failed\n");
885 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
886 program_name);
887 exit(1);
888 }
889 attrs[0]->attrname = "objectClass";
890 attrs[0]->attrvalue = newattr;
891 attrs[0]->value_count = 1;
892
893 /* set publickey */
894 newattr = (char **)calloc(2, sizeof (char *));
895 newattr[0] = pkeyatval;
896 newattr[1] = NULL;
897 if ((attrs[1] = (ns_ldap_attr_t *)calloc(1,
898 sizeof (ns_ldap_attr_t))) == NULL) {
899 FREE_CREDINFO(ckeyatval);
900 FREE_CREDINFO(pkeyatval);
901 FREE_CREDINFO(bindPasswd);
902 FREE_CREDINFO(bindDN);
903 fprintf(stderr, "Memory allocation failed\n");
904 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
905 program_name);
906 exit(1);
907 }
908 attrs[1]->attrname = "nisPublicKey";
909 attrs[1]->attrvalue = newattr;
910 attrs[1]->value_count = 1;
911
912 /* set privatekey */
913 newattr = (char **)calloc(2, sizeof (char *));
914 newattr[0] = ckeyatval;
915 newattr[1] = NULL;
916 if ((attrs[2] = (ns_ldap_attr_t *)calloc(1,
917 sizeof (ns_ldap_attr_t))) == NULL) {
918 FREE_CREDINFO(ckeyatval);
919 FREE_CREDINFO(pkeyatval);
920 FREE_CREDINFO(bindPasswd);
921 FREE_CREDINFO(bindDN);
922 fprintf(stderr, "Memory allocation failed\n");
923 fprintf(stderr, "%s: key-pair(s) unchanged.\n",
924 program_name);
925 exit(1);
926 }
927 attrs[2]->attrname = "nisSecretKey";
928 attrs[2]->attrvalue = newattr;
929 attrs[2]->value_count = 1;
930
931 /* terminator */
932 attrs[3] = NULL;
933
934 update_ldap_attr(dn, attrs, passwd, TRUE, update4host,
935 bindDN, bindPasswd);
936 } else {
937 /* object class already exists, replace keys */
938 ns_ldap_attr_t *attrs[4]; /* objectclass, pk, sk, NULL */
939
940 if (!ldap_attr_mod(&res->entry[0], mechname,
941 pkeyatval, &pattrs,
942 ckeyatval, &cattrs)) {
943 FREE_CREDINFO(ckeyatval);
944 FREE_CREDINFO(pkeyatval);
945 FREE_CREDINFO(bindPasswd);
946 FREE_CREDINFO(bindDN);
947 fprintf(stderr,
948 "Could not generate LDAP attribute list.\n");
949 fprintf(stderr,
950 "%s: key-pair(s) unchanged.\n", program_name);
951 exit(1);
952 }
953
954 attrs[0] = pattrs;
955 attrs[1] = cattrs;
956 attrs[2] = NULL;
957
958 update_ldap_attr(dn, attrs, passwd, FALSE, update4host,
959 bindDN, bindPasswd);
960 }
961
962 FREE_CREDINFO(ckeyatval);
963 FREE_CREDINFO(pkeyatval);
964 FREE_CREDINFO(bindPasswd);
965 FREE_CREDINFO(bindDN);
966
967 return (0);
968 }
969