2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * kadmin/ldap_util/kdb5_ldap_services.c
10 /* Copyright (c) 2004-2005, Novell, Inc.
11 * All rights reserved.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
16 * * Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 * * Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * * The copyright holder's name is not used to endorse or promote products
22 * derived from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
38 * Create / Delete / Modify / View / List service objects.
42 * Service objects have rights over realm objects and principals. The following
43 * functions manage the service objects.
48 #include <libintl.h> /* Solaris Kerberos */
49 #include <locale.h> /* Solaris Kerberos */
50 #include "kdb5_ldap_util.h"
51 #include "kdb5_ldap_list.h"
53 #ifdef HAVE_EDIRECTORY
56 rem_service_entry_from_file(int argc
,
59 char *service_object
);
62 extern krb5_boolean db_inited
;
64 static int process_host_list(char **host_list
, int servicetype
)
66 krb5_error_code retval
= 0;
68 char host_str
[MAX_LEN_LIST_ENTRY
] = "", proto_str
[PROTOCOL_STR_LEN
+ 1] = "", port_str
[PORT_STR_LEN
+ 1] = "";
71 /* Protocol and port number processing */
72 for (j
= 0; host_list
[j
]; j
++) {
73 /* Look for one hash */
74 if ((pchr
= strchr(host_list
[j
], HOST_INFO_DELIMITER
))) {
75 unsigned int hostname_len
= pchr
- host_list
[j
];
77 /* Check input for buffer overflow */
78 if (hostname_len
>= MAX_LEN_LIST_ENTRY
) {
83 /* First copy off the host name portion */
84 strncpy (host_str
, host_list
[j
], hostname_len
);
86 /* Parse for the protocol string and translate to number */
87 strncpy (proto_str
, pchr
+ 1, PROTOCOL_STR_LEN
);
88 if (!strcmp(proto_str
, "udp"))
89 sprintf (proto_str
, "%d", PROTOCOL_NUM_UDP
);
90 else if (!strcmp(proto_str
, "tcp"))
91 sprintf (proto_str
, "%d", PROTOCOL_NUM_TCP
);
93 proto_str
[0] = '\0'; /* Make the string null if invalid */
95 /* Look for one more hash */
96 if ((pchr
= strchr(pchr
+ 1, HOST_INFO_DELIMITER
))) {
97 /* Parse for the port string and check if it is numeric */
98 strncpy (port_str
, pchr
+ 1, PORT_STR_LEN
);
99 if (!strtol(port_str
, NULL
, 10)) /* Not a valid number */
103 } else { /* We have only host name */
104 strncpy (host_str
, host_list
[j
], MAX_LEN_LIST_ENTRY
- 1);
109 /* Now, based on service type, fill in suitable protocol
110 and port values if they are absent or not matching */
111 if (servicetype
== LDAP_KDC_SERVICE
) {
112 if (proto_str
[0] == '\0')
113 sprintf (proto_str
, "%d", PROTOCOL_DEFAULT_KDC
);
115 if (port_str
[0] == '\0')
116 sprintf (port_str
, "%d", PORT_DEFAULT_KDC
);
117 } else if (servicetype
== LDAP_ADMIN_SERVICE
) {
118 if (proto_str
[0] == '\0')
119 sprintf (proto_str
, "%d", PROTOCOL_DEFAULT_ADM
);
120 else if (strcmp(proto_str
, "1")) {
121 sprintf (proto_str
, "%d", PROTOCOL_DEFAULT_ADM
);
123 /* Print warning message */
124 printf (gettext("Admin Server supports only TCP protocol, hence setting that\n"));
127 if (port_str
[0] == '\0')
128 sprintf (port_str
, "%d", PORT_DEFAULT_ADM
);
129 } else if (servicetype
== LDAP_PASSWD_SERVICE
) {
130 if (proto_str
[0] == '\0')
131 sprintf (proto_str
, "%d", PROTOCOL_DEFAULT_PWD
);
132 else if (strcmp(proto_str
, "0")) {
133 sprintf (proto_str
, "%d", PROTOCOL_DEFAULT_PWD
);
135 /* Print warning message */
136 printf (gettext("Password Server supports only UDP protocol, hence setting that\n"));
139 if (port_str
[0] == '\0')
140 sprintf (port_str
, "%d", PORT_DEFAULT_PWD
);
143 /* Finally form back the string */
145 host_list
[j
] = (char*) malloc(sizeof(char) *
146 (strlen(host_str
) + strlen(proto_str
) + strlen(port_str
) + 2 + 1));
147 if (host_list
[j
] == NULL
) {
151 snprintf (host_list
[j
], strlen(host_str
) + strlen(proto_str
) + strlen(port_str
) + 2 + 1,
152 "%s#%s#%s", host_str
, proto_str
, port_str
);
161 * Given a realm name, this function will convert it to a DN by appending the
162 * Kerberos container location.
164 static krb5_error_code
165 convert_realm_name2dn_list(list
, krbcontainer_loc
)
167 const char *krbcontainer_loc
;
169 krb5_error_code retval
= 0;
170 char temp_str
[MAX_DN_CHARS
] = "\0";
171 char *temp_node
= NULL
;
178 for (i
= 0; (list
[i
] != NULL
) && (i
< MAX_LIST_ENTRIES
); i
++) {
179 /* Restrict copying to max. length to avoid buffer overflow */
180 snprintf (temp_str
, MAX_DN_CHARS
, "cn=%s,%s", list
[i
], krbcontainer_loc
);
182 /* Make copy of string to temporary node */
183 temp_node
= strdup(temp_str
);
184 if (list
[i
] == NULL
) {
189 /* On success, free list node and attach new one */
201 * This function will create a service object on the LDAP Server, with the
202 * specified attributes.
204 void kdb5_ldap_create_service(argc
, argv
)
208 /* Solaris Kerberos */
210 krb5_error_code retval
= 0;
211 krb5_ldap_service_params
*srvparams
= NULL
;
212 krb5_boolean print_usage
= FALSE
;
213 krb5_boolean no_msg
= FALSE
;
215 char **extra_argv
= NULL
;
218 krb5_ldap_realm_params
*rparams
= NULL
;
221 char **temprdns
= NULL
;
222 char *realmName
= NULL
;
223 kdb5_dal_handle
*dal_handle
= NULL
;
224 krb5_ldap_context
*ldap_context
=NULL
;
225 krb5_boolean service_obj_created
= FALSE
;
227 /* Check for number of arguments */
228 if ((argc
< 3) || (argc
> 10)) {
233 /* Allocate memory for service parameters structure */
234 srvparams
= (krb5_ldap_service_params
*) calloc(1, sizeof(krb5_ldap_service_params
));
235 if (srvparams
== NULL
) {
240 dal_handle
= (kdb5_dal_handle
*) util_context
->db_context
;
241 ldap_context
= (krb5_ldap_context
*) dal_handle
->db_context
;
243 /* Allocate memory for extra arguments to be used for setting
244 password -- it's OK to allocate as much as the total number
246 extra_argv
= (char **) calloc((unsigned int)argc
, sizeof(char*));
247 if (extra_argv
== NULL
) {
252 /* Set first of the extra arguments as the program name */
256 /* Read Kerberos container info, to construct realm DN from name
257 * and for assigning rights
259 if ((retval
= krb5_ldap_read_krbcontainer_params(util_context
,
260 &(ldap_context
->krbcontainer
)))) {
261 com_err(me
, retval
, gettext("while reading Kerberos container information"));
265 /* Parse all arguments */
266 for (i
= 1; i
< argc
; i
++) {
267 if (!strcmp(argv
[i
], "-kdc")) {
268 srvparams
->servicetype
= LDAP_KDC_SERVICE
;
269 } else if (!strcmp(argv
[i
], "-admin")) {
270 srvparams
->servicetype
= LDAP_ADMIN_SERVICE
;
271 } else if (!strcmp(argv
[i
], "-pwd")) {
272 srvparams
->servicetype
= LDAP_PASSWD_SERVICE
;
273 } else if (!strcmp(argv
[i
], "-servicehost")) {
277 srvparams
->krbhostservers
= (char **)calloc(MAX_LIST_ENTRIES
,
279 if (srvparams
->krbhostservers
== NULL
) {
284 if ((retval
= krb5_parse_list(argv
[i
], LIST_DELIMITER
,
285 srvparams
->krbhostservers
))) {
289 if ((retval
= process_host_list (srvparams
->krbhostservers
,
290 srvparams
->servicetype
))) {
294 mask
|= LDAP_SERVICE_HOSTSERVER
;
295 } else if (!strcmp(argv
[i
], "-realm")) {
299 srvparams
->krbrealmreferences
= (char **)calloc(MAX_LIST_ENTRIES
,
301 if (srvparams
->krbrealmreferences
== NULL
) {
306 if ((retval
= krb5_parse_list(argv
[i
], LIST_DELIMITER
,
307 srvparams
->krbrealmreferences
))) {
311 /* Convert realm names to realm DNs */
312 if ((retval
= convert_realm_name2dn_list(
313 srvparams
->krbrealmreferences
,
314 ldap_context
->krbcontainer
->DN
))) {
318 mask
|= LDAP_SERVICE_REALMREFERENCE
;
320 /* If argument is none of the above and beginning with '-',
321 * it must be related to password -- collect it
322 * to pass onto kdb5_ldap_set_service_password()
324 else if (*(argv
[i
]) == '-') {
325 /* Checking for options of setting the password for the
326 * service (by using 'setsrvpw') is not modular. --need to
327 * have a common function that can be shared with 'setsrvpw'
329 if (!strcmp(argv
[i
], "-randpw")) {
330 extra_argv
[extra_argc
] = argv
[i
];
332 } else if (!strcmp(argv
[i
], "-fileonly")) {
333 extra_argv
[extra_argc
] = argv
[i
];
336 /* For '-f' option alone, pick up the following argument too */
337 else if (!strcmp(argv
[i
], "-f")) {
338 extra_argv
[extra_argc
] = argv
[i
];
344 extra_argv
[extra_argc
] = argv
[i
];
346 } else { /* Any other option is invalid */
350 } else { /* Any other argument must be service DN */
351 /* First check if service DN is already provided --
352 * if so, there's a usage error
354 if (srvparams
->servicedn
!= NULL
) {
355 com_err(me
, EINVAL
, gettext("while creating service object"));
359 /* If not present already, fill up service DN */
360 srvparams
->servicedn
= strdup(argv
[i
]);
361 if (srvparams
->servicedn
== NULL
) {
362 com_err(me
, ENOMEM
, gettext("while creating service object"));
368 /* No point in proceeding further if service DN value is not available */
369 if (srvparams
->servicedn
== NULL
) {
370 com_err(me
, EINVAL
, gettext("while creating service object"));
374 if (srvparams
->servicetype
== 0) { /* Not provided and hence not set */
375 com_err(me
, EINVAL
, gettext("while creating service object"));
379 /* Create object with all attributes provided */
380 if ((retval
= krb5_ldap_create_service(util_context
, srvparams
, mask
)))
383 service_obj_created
= TRUE
;
385 /* ** NOTE ** srvparams structure should not be modified, as it is
386 * used for deletion of the service object in case of any failures
390 /* Set password too */
391 if (extra_argc
>= 1) {
392 /* Set service DN as the last argument */
393 extra_argv
[extra_argc
] = strdup(srvparams
->servicedn
);
394 if (extra_argv
[extra_argc
] == NULL
) {
400 if ((retval
= kdb5_ldap_set_service_password(extra_argc
, extra_argv
)) != 0) {
404 /* Rights assignment */
405 if (mask
& LDAP_SERVICE_REALMREFERENCE
) {
407 printf("%s", gettext("Changing rights for the service object. Please wait ... "));
411 rightsmask
|= LDAP_REALM_RIGHTS
;
412 rightsmask
|= LDAP_SUBTREE_RIGHTS
;
414 if ((srvparams
!= NULL
) && (srvparams
->krbrealmreferences
!= NULL
)) {
415 for (i
=0; (srvparams
->krbrealmreferences
[i
] != NULL
); i
++) {
417 /* Get the realm name, not the dn */
418 temprdns
= ldap_explode_dn(srvparams
->krbrealmreferences
[i
], 1);
420 if (temprdns
[0] == NULL
) {
425 realmName
= strdup(temprdns
[0]);
426 if (realmName
== NULL
) {
431 if ((retval
= krb5_ldap_read_realm_params(util_context
,
432 realmName
, &rparams
, &rmask
))) {
433 com_err(me
, retval
, gettext("while reading information of realm '%s'"),
438 if ((retval
= krb5_ldap_add_service_rights(util_context
,
439 srvparams
->servicetype
, srvparams
->servicedn
,
440 realmName
, rparams
->subtree
, rightsmask
))) {
441 printf(gettext("failed\n"));
442 com_err(me
, retval
, gettext("while assigning rights '%s'"),
443 srvparams
->servicedn
);
448 krb5_ldap_free_realm_params(rparams
);
451 printf(gettext("done\n"));
463 if ((retval
!= 0) && (service_obj_created
== TRUE
)) {
464 /* This is for deleting the service object if something goes
465 * wrong in creating the service object
468 /* srvparams is populated from the user input and should be correct as
469 * we were successful in creating a service object. Reusing the same
471 krb5_ldap_delete_service(util_context
, srvparams
, srvparams
->servicedn
);
474 /* Clean-up structure */
475 krb5_ldap_free_service (util_context
, srvparams
);
486 db_usage (CREATE_SERVICE
);
490 com_err(me
, retval
, gettext("while creating service object"));
500 * This function will modify the attributes of a given service
501 * object on the LDAP Server
503 void kdb5_ldap_modify_service(argc
, argv
)
507 /* Solaris Kerberos */
509 krb5_error_code retval
= 0;
510 krb5_ldap_service_params
*srvparams
= NULL
;
511 krb5_boolean print_usage
= FALSE
;
512 krb5_boolean no_msg
= FALSE
;
513 char *servicedn
= NULL
;
515 int in_mask
= 0, out_mask
= 0;
516 int srvhost_flag
= 0, realmdn_flag
= 0;
518 int existing_entries
= 0, new_entries
= 0;
519 char **temp_ptr
= NULL
;
520 krb5_ldap_realm_params
*rparams
= NULL
;
524 char **oldrealmrefs
= NULL
;
525 char **newrealmrefs
= NULL
;
526 char **temprdns
= NULL
;
527 char *realmName
= NULL
;
528 kdb5_dal_handle
*dal_handle
= NULL
;
529 krb5_ldap_context
*ldap_context
=NULL
;
531 /* Check for number of arguments */
532 if ((argc
< 3) || (argc
> 10)) {
537 dal_handle
= (kdb5_dal_handle
*) util_context
->db_context
;
538 ldap_context
= (krb5_ldap_context
*) dal_handle
->db_context
;
540 /* Parse all arguments, only to pick up service DN (Pass 1) */
541 for (i
= 1; i
< argc
; i
++) {
542 /* Skip arguments next to 'servicehost'
543 and 'realmdn' arguments */
544 if (!strcmp(argv
[i
], "-servicehost")) {
546 } else if (!strcmp(argv
[i
], "-clearservicehost")) {
548 } else if (!strcmp(argv
[i
], "-addservicehost")) {
550 } else if (!strcmp(argv
[i
], "-realm")) {
552 } else if (!strcmp(argv
[i
], "-clearrealm")) {
554 } else if (!strcmp(argv
[i
], "-addrealm")) {
556 } else { /* Any other argument must be service DN */
557 /* First check if service DN is already provided --
558 if so, there's a usage error */
559 if (servicedn
!= NULL
) {
560 com_err(me
, EINVAL
, gettext("while modifying service object"));
564 /* If not present already, fill up service DN */
565 servicedn
= strdup(argv
[i
]);
566 if (servicedn
== NULL
) {
567 com_err(me
, ENOMEM
, gettext("while modifying service object"));
573 /* No point in proceeding further if service DN value is not available */
574 if (servicedn
== NULL
) {
575 com_err(me
, EINVAL
, gettext("while modifying service object"));
579 retval
= krb5_ldap_read_service(util_context
, servicedn
, &srvparams
, &in_mask
);
581 /* Solaris Kerberos */
582 com_err(me
, retval
, gettext("while reading information of service '%s'"),
587 /* Read Kerberos container info, to construct realm DN from name
588 * and for assigning rights
590 if ((retval
= krb5_ldap_read_krbcontainer_params(util_context
,
591 &(ldap_context
->krbcontainer
)))) {
592 com_err(me
, retval
, gettext("while reading Kerberos container information"));
596 /* Parse all arguments, but skip the service DN (Pass 2) */
597 for (i
= 1; i
< argc
; i
++) {
598 if (!strcmp(argv
[i
], "-servicehost")) {
602 /* Free the old list if available */
603 if (srvparams
->krbhostservers
) {
604 krb5_free_list_entries (srvparams
->krbhostservers
);
605 free (srvparams
->krbhostservers
);
608 srvparams
->krbhostservers
= (char **)calloc(MAX_LIST_ENTRIES
,
610 if (srvparams
->krbhostservers
== NULL
) {
615 if ((retval
= krb5_parse_list(argv
[i
], LIST_DELIMITER
,
616 srvparams
->krbhostservers
))) {
620 if ((retval
= process_host_list (srvparams
->krbhostservers
,
621 srvparams
->servicetype
))) {
625 out_mask
|= LDAP_SERVICE_HOSTSERVER
;
627 /* Set flag to ignore 'add' and 'clear' */
629 } else if (!strcmp(argv
[i
], "-clearservicehost")) {
634 /* If attribute doesn't exist, don't permit 'clear' option */
635 if ((in_mask
& LDAP_SERVICE_HOSTSERVER
) == 0) {
636 /* Send out some proper error message here */
637 com_err(me
, EINVAL
, gettext("service host list is empty\n"));
641 /* Allocate list for processing */
642 list
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
648 if ((retval
= krb5_parse_list(argv
[i
], LIST_DELIMITER
, list
)))
651 if ((retval
= process_host_list (list
, srvparams
->servicetype
))) {
655 list_modify_str_array(&(srvparams
->krbhostservers
),
656 (const char**)list
, LIST_MODE_DELETE
);
658 out_mask
|= LDAP_SERVICE_HOSTSERVER
;
664 } else if (!strcmp(argv
[i
], "-addservicehost")) {
669 /* Allocate list for processing */
670 list
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
676 if ((retval
= krb5_parse_list(argv
[i
], LIST_DELIMITER
, list
)))
679 if ((retval
= process_host_list (list
, srvparams
->servicetype
))) {
683 /* Call list_modify_str_array() only if host server attribute
684 * exists already --Actually, it's better to handle this
685 * within list_modify_str_array()
687 if (in_mask
& LDAP_SERVICE_HOSTSERVER
) {
688 /* Re-size existing list */
689 existing_entries
= list_count_str_array(srvparams
->krbhostservers
);
690 new_entries
= list_count_str_array(list
);
691 temp_ptr
= (char **) realloc(srvparams
->krbhostservers
,
692 sizeof(char *) * (existing_entries
+ new_entries
+ 1));
693 if (temp_ptr
== NULL
) {
697 srvparams
->krbhostservers
= temp_ptr
;
699 list_modify_str_array(&(srvparams
->krbhostservers
),
700 (const char**)list
, LIST_MODE_ADD
);
706 srvparams
->krbhostservers
= list
;
708 out_mask
|= LDAP_SERVICE_HOSTSERVER
;
710 } else if (!strcmp(argv
[i
], "-realm")) {
714 if ((in_mask
& LDAP_SERVICE_REALMREFERENCE
) && (srvparams
->krbrealmreferences
)) {
716 /* Store the old realm list for removing rights */
717 oldrealmrefs
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
718 if (oldrealmrefs
== NULL
) {
723 for (j
= 0; srvparams
->krbrealmreferences
[j
] != NULL
; j
++) {
724 oldrealmrefs
[j
] = strdup(srvparams
->krbrealmreferences
[j
]);
725 if (oldrealmrefs
[j
] == NULL
) {
730 oldrealmrefs
[j
] = NULL
;
733 /* Free the old list if available */
734 krb5_free_list_entries (srvparams
->krbrealmreferences
);
735 free (srvparams
->krbrealmreferences
);
738 srvparams
->krbrealmreferences
= (char **)calloc(MAX_LIST_ENTRIES
,
740 if (srvparams
->krbrealmreferences
== NULL
) {
745 if ((retval
= krb5_parse_list(argv
[i
], LIST_DELIMITER
,
746 srvparams
->krbrealmreferences
))) {
750 /* Convert realm names to realm DNs */
751 if ((retval
= convert_realm_name2dn_list(
752 srvparams
->krbrealmreferences
,
753 ldap_context
->krbcontainer
->DN
))) {
757 out_mask
|= LDAP_SERVICE_REALMREFERENCE
;
759 /* Set flag to ignore 'add' and 'clear' */
761 } else if (!strcmp(argv
[i
], "-clearrealm")) {
766 /* If attribute doesn't exist, don't permit 'clear' option */
767 if (((in_mask
& LDAP_SERVICE_REALMREFERENCE
) == 0) || (srvparams
->krbrealmreferences
== NULL
)) {
768 /* Send out some proper error message here */
773 /* Store the old realm list for removing rights */
774 oldrealmrefs
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
775 if (oldrealmrefs
== NULL
) {
780 for (j
= 0; srvparams
->krbrealmreferences
[j
] != NULL
; j
++) {
781 oldrealmrefs
[j
] = strdup(srvparams
->krbrealmreferences
[j
]);
782 if (oldrealmrefs
[j
] == NULL
) {
787 oldrealmrefs
[j
] = NULL
;
790 /* Allocate list for processing */
791 list
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
797 if ((retval
= krb5_parse_list(argv
[i
], LIST_DELIMITER
, list
)))
800 /* Convert realm names to realm DNs */
801 if ((retval
= convert_realm_name2dn_list(list
,
802 ldap_context
->krbcontainer
->DN
))) {
806 list_modify_str_array(&(srvparams
->krbrealmreferences
),
807 (const char**)list
, LIST_MODE_DELETE
);
809 out_mask
|= LDAP_SERVICE_REALMREFERENCE
;
815 } else if (!strcmp(argv
[i
], "-addrealm")) {
820 /* Allocate list for processing */
821 list
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
827 if ((retval
= krb5_parse_list(argv
[i
], LIST_DELIMITER
, list
)))
830 /* Convert realm names to realm DNs */
831 if ((retval
= convert_realm_name2dn_list(list
,
832 ldap_context
->krbcontainer
->DN
))) {
836 if ((in_mask
& LDAP_SERVICE_REALMREFERENCE
) && (srvparams
->krbrealmreferences
) && (!oldrealmrefs
)) {
837 /* Store the old realm list for removing rights */
838 oldrealmrefs
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
839 if (oldrealmrefs
== NULL
) {
844 for (j
= 0; srvparams
->krbrealmreferences
[j
] != NULL
; j
++) {
845 oldrealmrefs
[j
] = strdup(srvparams
->krbrealmreferences
[j
]);
846 if (oldrealmrefs
[j
] == NULL
) {
851 oldrealmrefs
[j
] = NULL
;
854 /* Call list_modify_str_array() only if realm DN attribute
855 * exists already -- Actually, it's better to handle this
856 * within list_modify_str_array() */
857 if (in_mask
& LDAP_SERVICE_REALMREFERENCE
) {
858 /* Re-size existing list */
859 existing_entries
= list_count_str_array(
860 srvparams
->krbrealmreferences
);
861 new_entries
= list_count_str_array(list
);
862 temp_ptr
= (char **) realloc(srvparams
->krbrealmreferences
,
863 sizeof(char *) * (existing_entries
+ new_entries
+ 1));
864 if (temp_ptr
== NULL
) {
868 srvparams
->krbrealmreferences
= temp_ptr
;
870 list_modify_str_array(&(srvparams
->krbrealmreferences
),
871 (const char**)list
, LIST_MODE_ADD
);
877 srvparams
->krbrealmreferences
= list
;
879 out_mask
|= LDAP_SERVICE_REALMREFERENCE
;
882 /* Any other argument must be service DN
887 /* Modify attributes of object */
888 if ((retval
= krb5_ldap_modify_service(util_context
, srvparams
, out_mask
)))
891 /* Service rights modification code */
892 if (out_mask
& LDAP_SERVICE_REALMREFERENCE
) {
894 printf("%s", gettext("Changing rights for the service object. Please wait ... "));
897 newrealmrefs
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
898 if (newrealmrefs
== NULL
) {
903 if ((srvparams
!= NULL
) && (srvparams
->krbrealmreferences
!= NULL
)) {
904 for (j
= 0; srvparams
->krbrealmreferences
[j
] != NULL
; j
++) {
905 newrealmrefs
[j
] = strdup(srvparams
->krbrealmreferences
[j
]);
906 if (newrealmrefs
[j
] == NULL
) {
911 newrealmrefs
[j
] = NULL
;
913 disjoint_members(oldrealmrefs
, newrealmrefs
);
915 /* Delete the rights for the given service, on each of the realm
916 * container & subtree in the old realm reference list.
920 rightsmask
|= LDAP_REALM_RIGHTS
;
921 rightsmask
|= LDAP_SUBTREE_RIGHTS
;
923 for (i
= 0; (oldrealmrefs
[i
] != NULL
); i
++) {
924 /* Get the realm name, not the dn */
925 temprdns
= ldap_explode_dn(oldrealmrefs
[i
], 1);
927 if (temprdns
[0] == NULL
) {
932 realmName
= strdup(temprdns
[0]);
933 if (realmName
== NULL
) {
938 if ((retval
= krb5_ldap_read_realm_params(util_context
,
939 realmName
, &rparams
, &rmask
))) {
940 com_err(me
, retval
, gettext("while reading information of realm '%s'"),
945 if ((retval
= krb5_ldap_delete_service_rights(util_context
,
946 srvparams
->servicetype
, srvparams
->servicedn
,
947 realmName
, rparams
->subtree
, rightsmask
))) {
948 printf(gettext("failed\n"));
949 com_err(me
, retval
, gettext("while assigning rights '%s'"),
950 srvparams
->servicedn
);
955 krb5_ldap_free_realm_params(rparams
);
959 /* Add the rights for the given service, on each of the realm
960 * container & subtree in the new realm reference list.
964 rightsmask
|= LDAP_REALM_RIGHTS
;
965 rightsmask
|= LDAP_SUBTREE_RIGHTS
;
967 for (i
= 0; (newrealmrefs
[i
] != NULL
); i
++) {
968 /* Get the realm name, not the dn */
969 temprdns
= ldap_explode_dn(newrealmrefs
[i
], 1);
971 if (temprdns
[0] == NULL
) {
976 realmName
= strdup(temprdns
[0]);
977 if (realmName
== NULL
) {
982 if ((retval
= krb5_ldap_read_krbcontainer_params(util_context
,
983 &(ldap_context
->krbcontainer
)))) {
985 gettext("while reading Kerberos container information"));
989 if ((retval
= krb5_ldap_read_realm_params(util_context
,
990 realmName
, &rparams
, &rmask
))) {
991 com_err(me
, retval
, gettext("while reading information of realm '%s'"),
996 if ((retval
= krb5_ldap_add_service_rights(util_context
,
997 srvparams
->servicetype
, srvparams
->servicedn
,
998 realmName
, rparams
->subtree
, rightsmask
))) {
999 printf(gettext("failed\n"));
1000 com_err(me
, retval
, gettext("while assigning rights '%s'"),
1001 srvparams
->servicedn
);
1006 krb5_ldap_free_realm_params(rparams
);
1010 printf(gettext("done\n"));
1022 /* Clean-up structure */
1023 krb5_ldap_free_service(util_context
, srvparams
);
1034 for (i
= 0; oldrealmrefs
[i
] != NULL
; i
++)
1035 free(oldrealmrefs
[i
]);
1040 for (i
= 0; newrealmrefs
[i
] != NULL
; i
++)
1041 free(newrealmrefs
[i
]);
1050 db_usage(MODIFY_SERVICE
);
1054 com_err(me
, retval
, gettext("while modifying service object"));
1063 * This function will delete the entry corresponding to the service object
1064 * from the service password file.
1066 static krb5_error_code
1067 rem_service_entry_from_file(argc
, argv
, file_name
, service_object
)
1071 char *service_object
;
1074 /* Solaris Kerberos */
1075 char *me
= progname
;
1076 char *tmp_file
= NULL
;
1079 unsigned int len
= 0;
1080 char line
[MAX_LEN
]={0};
1081 mode_t omask
= umask(077);
1083 /* Check for permissions on the password file */
1084 if (access(file_name
, W_OK
) == -1) {
1085 /* If the specified file itself is not there, no need to show error */
1086 if (errno
== ENOENT
) {
1090 com_err(me
, errno
, gettext("while deleting entry from file %s", file_name
));
1095 /* Create a temporary file which contains all the entries except the
1096 entry for the given service dn */
1097 pfile
= fopen(file_name
, "r+F");
1098 if (pfile
== NULL
) {
1099 com_err(me
, errno
, gettext("while deleting entry from file %s"), file_name
);
1103 /* Create a new file with the extension .tmp */
1104 tmp_file
= (char *)malloc(strlen(file_name
) + 4 + 1);
1105 if (tmp_file
== NULL
) {
1106 com_err(me
, ENOMEM
, gettext("while deleting entry from file"));
1110 snprintf (tmp_file
, strlen(file_name
) + 4 + 1, "%s%s", file_name
, ".tmp");
1113 tmpfd
= creat(tmp_file
, S_IRUSR
|S_IWUSR
);
1116 com_err(me
, errno
, gettext("while deleting entry from file\n"));
1121 /* Copy only those lines which donot have the specified service dn */
1122 while (fgets(line
, MAX_LEN
, pfile
) != NULL
) {
1123 if ((strstr(line
, service_object
) != NULL
) &&
1124 (line
[strlen(service_object
)] == '#')) {
1128 if (write(tmpfd
, line
, len
) != len
) {
1129 com_err(me
, errno
, gettext("while deleting entry from file\n"));
1139 if (unlink(file_name
) == 0) {
1140 link(tmp_file
, file_name
);
1142 com_err(me
, errno
, gettext("while deleting entry from file\n"));
1158 * This function will delete the service object from the LDAP Server
1159 * and unlink the references to the Realm objects (if any)
1162 kdb5_ldap_destroy_service(argc
, argv
)
1168 krb5_error_code retval
= EINVAL
;
1170 char *servicedn
= NULL
;
1171 char *stashfilename
= NULL
;
1173 krb5_ldap_service_params
*lserparams
= NULL
;
1174 krb5_boolean print_usage
= FALSE
;
1176 if ((argc
< 2) || (argc
> 5)) {
1181 for (i
=1; i
< argc
; i
++) {
1183 if (strcmp(argv
[i
],"-force")==0) {
1185 } else if (strcmp(argv
[i
],"-f")==0) {
1187 stashfilename
=strdup(argv
[i
+1]);
1188 if (stashfilename
== NULL
) {
1189 /* Solaris Kerberos */
1190 com_err(progname
, ENOMEM
, gettext("while destroying service"));
1200 if ((argv
[i
]) && (servicedn
== NULL
)) {
1201 servicedn
=strdup(argv
[i
]);
1202 if (servicedn
== NULL
) {
1203 /* Solaris Kerberos */
1204 com_err(progname
, ENOMEM
, gettext("while destroying service"));
1221 printf(gettext("This will delete the service object '%s', are you sure?\n"), servicedn
);
1222 printf(gettext("(type 'yes' to confirm)? "));
1223 if (fgets(buf
, sizeof(buf
), stdin
) == NULL
) {
1227 if (strcmp(buf
, yes
)) {
1233 if ((retval
= krb5_ldap_read_service(util_context
, servicedn
,
1234 &lserparams
, &mask
))) {
1235 /* Solaris Kerberos */
1236 com_err(progname
, retval
, gettext("while destroying service '%s'"), servicedn
);
1241 retval
= krb5_ldap_delete_service(util_context
, lserparams
, servicedn
);
1244 /* Solaris Kerberos */
1245 com_err(progname
, retval
, gettext("while destroying service '%s'"), servicedn
);
1250 if (stashfilename
== NULL
) {
1251 stashfilename
= strdup(DEF_SERVICE_PASSWD_FILE
);
1252 if (stashfilename
== NULL
) {
1253 /* Solaris Kerberos */
1254 com_err(progname
, ENOMEM
, gettext("while destroying service"));
1259 printf(gettext("** service object '%s' deleted.\n"), servicedn
);
1260 retval
= rem_service_entry_from_file(argc
, argv
, stashfilename
, servicedn
);
1263 printf(gettext("** error removing service object entry '%s' from password file.\n"),
1275 krb5_ldap_free_service(util_context
, lserparams
);
1282 if (stashfilename
) {
1283 free(stashfilename
);
1287 db_usage(DESTROY_SERVICE
);
1295 * This function will display information about the given service object
1297 void kdb5_ldap_view_service(argc
, argv
)
1301 krb5_ldap_service_params
*lserparams
= NULL
;
1302 krb5_error_code retval
= 0;
1303 char *servicedn
= NULL
;
1305 krb5_boolean print_usage
= FALSE
;
1312 servicedn
=strdup(argv
[1]);
1313 if (servicedn
== NULL
) {
1314 /* Solaris Kerberos */
1315 com_err(progname
, ENOMEM
, gettext("while viewing service"));
1320 if ((retval
= krb5_ldap_read_service(util_context
, servicedn
, &lserparams
, &mask
))) {
1321 /* Solaris Kerberos */
1322 com_err(progname
, retval
, gettext("while viewing service '%s'"), servicedn
);
1327 print_service_params(lserparams
, mask
);
1337 krb5_ldap_free_service(util_context
, lserparams
);
1344 db_usage(VIEW_SERVICE
);
1352 * This function will list the DNs of kerberos services present on
1353 * the LDAP Server under a specific sub-tree (entire tree by default)
1355 void kdb5_ldap_list_services(argc
, argv
)
1359 /* Solaris Kerberos */
1360 char *me
= progname
;
1361 krb5_error_code retval
= 0;
1362 char *basedn
= NULL
;
1364 char **plist
= NULL
;
1365 krb5_boolean print_usage
= FALSE
;
1367 /* Check for number of arguments */
1368 if ((argc
!= 1) && (argc
!= 3)) {
1373 /* Parse base DN argument if present */
1375 if (strcmp(argv
[1], "-basedn")) {
1380 basedn
= strdup(argv
[2]);
1381 if (basedn
== NULL
) {
1382 com_err(me
, ENOMEM
, gettext("while listing services"));
1388 retval
= krb5_ldap_list_services(util_context
, basedn
, &list
);
1389 if ((retval
!= 0) || (list
== NULL
)) {
1394 for (plist
= list
; *plist
!= NULL
; plist
++) {
1395 printf("%s\n", *plist
);
1405 krb5_free_list_entries (list
);
1413 db_usage(LIST_SERVICE
);
1417 com_err(me
, retval
, gettext("while listing policy objects"));
1426 * This function will print the service object information
1427 * to the standard output
1430 print_service_params(lserparams
, mask
)
1431 krb5_ldap_service_params
*lserparams
;
1436 /* Print the service dn */
1437 printf("%20s%-20s\n", gettext("Service dn: "), lserparams
->servicedn
);
1439 /* Print the service type of the object to be read */
1440 if (lserparams
->servicetype
== LDAP_KDC_SERVICE
) {
1441 printf("%20s%-20s\n", gettext("Service type: "), "kdc");
1442 } else if (lserparams
->servicetype
== LDAP_ADMIN_SERVICE
) {
1443 printf("%20s%-20s\n", gettext("Service type: "), "admin");
1444 } else if (lserparams
->servicetype
== LDAP_PASSWD_SERVICE
) {
1445 printf("%20s%-20s\n", gettext("Service type: "), "pwd");
1448 /* Print the host server values */
1449 printf("%20s\n", gettext("Service host list: "));
1450 if (mask
& LDAP_SERVICE_HOSTSERVER
) {
1451 for (i
=0; lserparams
->krbhostservers
[i
] != NULL
; ++i
) {
1452 printf("%20s%-50s\n","",lserparams
->krbhostservers
[i
]);
1456 /* Print the realm reference dn values */
1457 printf("%20s\n", gettext("Realm DN list: "));
1458 if (mask
& LDAP_SERVICE_REALMREFERENCE
) {
1459 for (i
=0; lserparams
&& lserparams
->krbrealmreferences
&& lserparams
->krbrealmreferences
[i
] != NULL
; ++i
) {
1460 printf("%20s%-50s\n","",lserparams
->krbrealmreferences
[i
]);
1469 * This function will generate random password of length(RANDOM_PASSWD_LEN)
1476 * RANDOM_PASSWD_LEN length random password
1478 static int generate_random_password(krb5_context ctxt
, char **randpwd
, unsigned int *passlen
)
1480 char *random_pwd
= NULL
;
1486 /* setting random password length in the range 16-32 */
1487 srand((unsigned int)(time(0) ^ getpid()));
1489 data
.length
= RANDOM_PASSWD_LEN
;
1490 random_pwd
= (char *)malloc(data
.length
+ 1);
1491 if (random_pwd
== NULL
) {
1492 com_err("setsrvpw", ENOMEM
, gettext("while generating random password"));
1495 memset(random_pwd
, 0, data
.length
+ 1);
1496 data
.data
= random_pwd
;
1498 ret
= krb5_c_random_make_octets(ctxt
, &data
);
1500 com_err("setsrvpw", ret
, gettext("Error generating random password"));
1505 for (i
=0; i
<data
.length
; i
++) {
1506 /* restricting to ascii chars. Need to change this when 8.8 supports */
1507 if ((unsigned char)random_pwd
[i
] > 127) {
1508 random_pwd
[i
] = (unsigned char)random_pwd
[i
] % 128;
1509 } else if (random_pwd
[i
] == 0) {
1510 random_pwd
[i
] = (rand()/(RAND_MAX
/127 + 1))+1;
1514 *randpwd
= random_pwd
;
1515 *passlen
= data
.length
;
1522 * This function will set the password of the service object in the directory
1523 * and/or the specified service password file.
1527 * argc - contains the number of arguments for this sub-command
1528 * argv - array of arguments for this sub-command
1534 kdb5_ldap_set_service_password(argc
, argv
)
1538 krb5_ldap_context
*lparams
= NULL
;
1539 char *file_name
= NULL
;
1540 char *tmp_file
= NULL
;
1541 /* Solaris Kerberos */
1542 char *me
= progname
;
1544 int random_passwd
= 0;
1545 int set_dir_pwd
= 1;
1546 krb5_boolean db_init_local
= FALSE
;
1547 char *service_object
= NULL
;
1548 char *passwd
= NULL
;
1549 char *prompt1
= NULL
;
1550 char *prompt2
= NULL
;
1551 unsigned int passwd_len
= 0;
1552 krb5_error_code errcode
= -1;
1553 int retval
= 0, i
= 0;
1554 unsigned int len
= 0;
1555 krb5_boolean print_usage
= FALSE
;
1559 kdb5_dal_handle
*dal_handle
= NULL
;
1560 struct data encrypted_passwd
= {0, NULL
};
1562 /* The arguments for setsrv password should contain the service object DN
1563 * and options to specify whether the password should be updated in file only
1564 * or both file and directory. So the possible combination of arguments are:
1565 * setsrvpw servicedn wherein argc is 2
1566 * setsrvpw -fileonly servicedn wherein argc is 3
1567 * setsrvpw -randpw servicedn wherein argc is 3
1568 * setsrvpw -f filename servicedn wherein argc is 4
1569 * setsrvpw -fileonly -f filename servicedn wherein argc is 5
1570 * setsrvpw -randpw -f filename servicedn wherein argc is 5
1572 if ((argc
< 2) || (argc
> 5)) {
1577 dal_handle
= (kdb5_dal_handle
*)util_context
->db_context
;
1578 lparams
= (krb5_ldap_context
*) dal_handle
->db_context
;
1580 if (lparams
== NULL
) {
1581 printf(gettext("%s: Invalid LDAP handle\n"), me
);
1585 /* Parse the arguments */
1586 for (i
= 1; i
< argc
-1 ; i
++) {
1587 if (strcmp(argv
[i
], "-randpw") == 0) {
1589 } else if (strcmp(argv
[i
], "-fileonly") == 0) {
1591 } else if (strcmp(argv
[i
], "-f") == 0) {
1592 if (argv
[++i
] == NULL
) {
1597 file_name
= strdup(argv
[i
]);
1598 if (file_name
== NULL
) {
1599 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1602 /* Verify if the file location has the proper file name
1603 * for eg, if the file location is a directory like /home/temp/,
1606 filelen
= strlen(file_name
);
1607 if ((filelen
== 0) || (file_name
[filelen
-1] == '/')) {
1608 printf(gettext("%s: Filename not specified for setting service object password\n"), me
);
1613 printf(gettext("%s: Invalid option specified for \"setsrvpw\" command\n"), me
);
1624 service_object
= strdup(argv
[i
]);
1625 if (service_object
== NULL
) {
1626 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1630 if (strlen(service_object
) == 0) {
1631 printf(gettext("%s: Service object not specified for \"setsrvpw\" command\n"), me
);
1636 if (service_object
[0] == '-') {
1641 if (file_name
== NULL
) {
1642 file_name
= strdup(DEF_SERVICE_PASSWD_FILE
);
1643 if (file_name
== NULL
) {
1644 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1650 if (db_inited
== FALSE
) {
1651 if ((errcode
= krb5_ldap_db_init(util_context
, lparams
))) {
1652 com_err(me
, errcode
, gettext("while initializing database"));
1655 db_init_local
= TRUE
;
1659 if (random_passwd
) {
1661 printf(gettext("%s: Invalid option specified for \"setsrvpw\" command\n"), me
);
1665 /* Generate random password */
1667 if ((errcode
= generate_random_password(util_context
, &passwd
, &passwd_len
))) {
1668 printf(gettext("%s: Failed to set service object password\n"), me
);
1671 passwd_len
= strlen(passwd
);
1674 /* Get the service object password from the terminal */
1675 passwd
= (char *)malloc(MAX_SERVICE_PASSWD_LEN
+ 1);
1676 if (passwd
== NULL
) {
1677 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1680 memset(passwd
, 0, MAX_SERVICE_PASSWD_LEN
+ 1);
1681 passwd_len
= MAX_SERVICE_PASSWD_LEN
;
1683 len
= strlen(service_object
);
1684 /* size of allocation=strlen of servicedn + strlen("Password for \" \"")=20 */
1685 prompt1
= (char *)malloc(len
+ 20);
1686 if (prompt1
== NULL
) {
1687 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1690 sprintf(prompt1
, gettext("Password for \"%s\""), service_object
);
1692 /* size of allocation=strlen of servicedn + strlen("Re-enter Password for \" \"")=30 */
1693 prompt2
= (char *)malloc(len
+ 30);
1694 if (prompt2
== NULL
) {
1695 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1699 sprintf(prompt2
, gettext("Re-enter password for \"%s\""), service_object
);
1701 retval
= krb5_read_password(util_context
, prompt1
, prompt2
, passwd
, &passwd_len
);
1705 com_err(me
, retval
, gettext("while setting service object password"));
1706 memset(passwd
, 0, MAX_SERVICE_PASSWD_LEN
);
1709 if (passwd_len
== 0) {
1710 printf(gettext("%s: Invalid password\n"), me
);
1711 memset(passwd
, 0, MAX_SERVICE_PASSWD_LEN
);
1714 passwd_len
= strlen(passwd
);
1717 /* Hex the password */
1720 pwd
.length
= passwd_len
;
1723 errcode
= tohex(pwd
, &hex
);
1725 if (hex
.length
!= 0) {
1726 memset(hex
.data
, 0, hex
.length
);
1729 com_err(me
, errcode
, gettext("Failed to convert the password to hex"));
1730 memset(passwd
, 0, passwd_len
);
1733 /* Password = {CRYPT}<encrypted password>:<encrypted key> */
1734 encrypted_passwd
.value
= (unsigned char *)malloc(strlen(service_object
) +
1735 1 + 5 + hex
.length
+ 2);
1736 if (encrypted_passwd
.value
== NULL
) {
1737 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1738 memset(passwd
, 0, passwd_len
);
1739 memset(hex
.data
, 0, hex
.length
);
1743 encrypted_passwd
.value
[strlen(service_object
) +
1744 1 + 5 + hex
.length
+ 1] = '\0';
1745 sprintf((char *)encrypted_passwd
.value
, "%s#{HEX}%s\n", service_object
, hex
.data
);
1746 encrypted_passwd
.len
= strlen((char *)encrypted_passwd
.value
);
1747 memset(hex
.data
, 0, hex
.length
);
1751 /* We should check if the file exists and we have permission to write into that file */
1752 if (access(file_name
, W_OK
) == -1) {
1753 if (errno
== ENOENT
) {
1757 printf(gettext("File does not exist. Creating the file %s...\n"), file_name
);
1759 fd
= creat(file_name
, S_IRUSR
|S_IWUSR
);
1762 com_err(me
, errno
, gettext("Error creating file %s"), file_name
);
1763 memset(passwd
, 0, passwd_len
);
1768 com_err(me
, errno
, gettext("Unable to access the file %s"), file_name
);
1769 memset(passwd
, 0, passwd_len
);
1775 if ((errcode
= krb5_ldap_set_service_passwd(util_context
, service_object
, passwd
)) != 0) {
1776 com_err(me
, errcode
, gettext("Failed to set password for service object %s"), service_object
);
1777 memset(passwd
, 0, passwd_len
);
1782 memset(passwd
, 0, passwd_len
);
1785 /* TODO: file lock for the service password file */
1786 /* set password in the file */
1787 pfile
= fopen(file_name
, "r+F");
1788 if (pfile
== NULL
) {
1789 com_err(me
, errno
, gettext("Failed to open file %s"), file_name
);
1793 while (fgets(line
, MAX_LEN
, pfile
) != NULL
) {
1794 if ((str
= strstr(line
, service_object
)) != NULL
) {
1795 if (line
[strlen(service_object
)] == '#') {
1803 /* If the service object dn is not present in the service password file */
1804 if (fwrite(encrypted_passwd
.value
, (unsigned int)encrypted_passwd
.len
, 1, pfile
) != 1) {
1805 com_err(me
, errno
, gettext("Failed to write service object password to file"));
1809 com_err(me
, errno
, gettext("Error reading service object password file"));
1815 /* Password entry for the service object is already present in the file */
1816 /* Delete the existing entry and add the new entry */
1817 FILE *newfile
= NULL
;
1820 /* Create a new file with the extension .tmp */
1821 tmp_file
= (char *) malloc(sizeof(char) * (strlen(file_name
) + 4 + 1));
1822 if (tmp_file
== NULL
) {
1823 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1826 sprintf(tmp_file
,"%s.%s",file_name
,"tmp");
1829 newfile
= fopen(tmp_file
, "w+F");
1831 if (newfile
== NULL
) {
1832 com_err(me
, errno
, gettext("Error creating file %s"), tmp_file
);
1837 fseek(pfile
, 0, SEEK_SET
);
1838 while (fgets(line
, MAX_LEN
, pfile
) != NULL
) {
1839 if (((str
= strstr(line
, service_object
)) != NULL
) && (line
[strlen(service_object
)] == '#')) {
1840 if (fprintf(newfile
, "%s", encrypted_passwd
.value
) < 0) {
1841 com_err(me
, errno
, gettext("Failed to write service object password to file"));
1848 if (fprintf(newfile
, "%s", line
) < 0) {
1849 com_err(me
, errno
, gettext("Failed to write service object password to file"));
1858 com_err(me
, errno
, gettext("Error reading service object password file"));
1864 /* TODO: file lock for the service password file */
1871 if (unlink(file_name
) == 0) {
1872 link(tmp_file
, file_name
);
1874 com_err(me
, errno
, gettext("Failed to write service object password to file"));
1884 krb5_ldap_close(util_context
);
1887 free(service_object
);
1895 if (encrypted_passwd
.value
) {
1896 memset(encrypted_passwd
.value
, 0, encrypted_passwd
.len
);
1897 free(encrypted_passwd
.value
);
1907 db_usage(SET_SRV_PW
);
1912 #else /* #ifdef HAVE_EDIRECTORY */
1915 * Convert the user supplied password into hexadecimal and stash it. Only a
1916 * little more secure than storing plain password in the file ...
1919 kdb5_ldap_stash_service_password(argc
, argv
)
1924 unsigned int passwd_len
= 0;
1925 /* Solaris Kerberos */
1926 char *me
= progname
;
1927 char *service_object
= NULL
;
1928 char *file_name
= NULL
, *tmp_file
= NULL
;
1929 char passwd
[MAX_SERVICE_PASSWD_LEN
];
1934 krb5_boolean print_usage
= FALSE
;
1935 krb5_data hexpasswd
= {0, 0, NULL
};
1936 mode_t old_mode
= 0;
1940 * stashsrvpw [-f filename] service_dn
1942 * 'service_dn' is the DN of the service object
1943 * 'filename' is the path of the stash file
1945 if (argc
!= 2 && argc
!= 4) {
1951 /* Find the stash file name */
1952 if (strcmp (argv
[1], "-f") == 0) {
1953 if (((file_name
= strdup (argv
[2])) == NULL
) ||
1954 ((service_object
= strdup (argv
[3])) == NULL
)) {
1955 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1958 } else if (strcmp (argv
[2], "-f") == 0) {
1959 if (((file_name
= strdup (argv
[3])) == NULL
) ||
1960 ((service_object
= strdup (argv
[1])) == NULL
)) {
1961 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1968 if (file_name
== NULL
) {
1969 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1972 } else { /* argc == 2 */
1975 service_object
= strdup (argv
[1]);
1976 if (service_object
== NULL
) {
1977 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1981 /* Pick up the stash-file name from krb5.conf */
1982 profile_get_string(util_context
->profile
, KDB_REALM_SECTION
,
1983 util_context
->default_realm
, KDB_MODULE_POINTER
, NULL
, §ion
);
1985 if (section
== NULL
) {
1986 profile_get_string(util_context
->profile
, KDB_MODULE_DEF_SECTION
,
1987 KDB_MODULE_POINTER
, NULL
, NULL
, §ion
);
1988 if (section
== NULL
) {
1989 /* Stash file path neither in krb5.conf nor on command line */
1990 file_name
= strdup(DEF_SERVICE_PASSWD_FILE
);
1991 if (file_name
== NULL
) {
1992 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1999 profile_get_string (util_context
->profile
, KDB_MODULE_SECTION
, section
,
2000 "ldap_service_password_file", NULL
, &file_name
);
2003 * Solaris Kerberos: use default if ldap_service_password_file not set
2005 if (file_name
== NULL
) {
2006 file_name
= strdup(DEF_SERVICE_PASSWD_FILE
);
2007 if (file_name
== NULL
) {
2008 com_err(me
, ENOMEM
, gettext("while setting service object password"));
2015 /* Get password from user */
2017 char prompt1
[256], prompt2
[256];
2019 /* Get the service object password from the terminal */
2020 memset(passwd
, 0, sizeof (passwd
));
2021 passwd_len
= sizeof (passwd
);
2023 /* size of prompt = strlen of servicedn + strlen("Password for \" \"") */
2024 assert (sizeof (prompt1
) > (strlen (service_object
)
2025 + sizeof ("Password for \" \"")));
2026 sprintf(prompt1
, gettext("Password for \"%s\""), service_object
);
2028 /* size of prompt = strlen of servicedn + strlen("Re-enter Password for \" \"") */
2029 assert (sizeof (prompt2
) > (strlen (service_object
)
2030 + sizeof ("Re-enter Password for \" \"")));
2031 sprintf(prompt2
, gettext("Re-enter password for \"%s\""), service_object
);
2033 ret
= krb5_read_password(util_context
, prompt1
, prompt2
, passwd
, &passwd_len
);
2035 com_err(me
, ret
, gettext("while setting service object password"));
2036 memset(passwd
, 0, sizeof (passwd
));
2040 if (passwd_len
== 0) {
2041 printf(gettext("%s: Invalid password\n"), me
);
2042 memset(passwd
, 0, MAX_SERVICE_PASSWD_LEN
);
2047 /* Convert the password to hexadecimal */
2051 pwd
.length
= passwd_len
;
2054 ret
= tohex(pwd
, &hexpasswd
);
2056 com_err(me
, ret
, gettext("Failed to convert the password to hexadecimal"));
2057 memset(passwd
, 0, passwd_len
);
2061 memset(passwd
, 0, passwd_len
);
2063 /* TODO: file lock for the service passowrd file */
2065 /* set password in the file */
2066 #if 0 /* ************ Begin IFDEF'ed OUT ***************************** */
2067 old_mode
= umask(0177);
2068 pfile
= fopen(file_name
, "a+");
2069 if (pfile
== NULL
) {
2070 com_err(me
, errno
, gettext("Failed to open file %s: %s"), file_name
,
2077 /* Solaris Kerberos: safer than the above */
2078 fd
= open(file_name
, O_CREAT
|O_RDWR
|O_APPEND
, 0600);
2080 com_err(me
, errno
, gettext("Failed to open file %s: %s"), file_name
,
2084 pfile
= fdopen(fd
, "a+F");
2085 if (pfile
== NULL
) {
2086 com_err(me
, errno
, gettext("Failed to open file %s: %s"), file_name
,
2093 while (fgets (line
, MAX_LEN
, pfile
) != NULL
) {
2094 if ((str
= strstr (line
, service_object
)) != NULL
) {
2096 * White spaces not allowed, # delimits the service dn from the
2099 if (line
[strlen (service_object
)] == '#')
2107 /* If the service object dn is not present in the service password file */
2108 if (fprintf(pfile
, "%s#{HEX}%s\n", service_object
, hexpasswd
.data
) < 0) {
2109 com_err(me
, errno
, gettext("Failed to write service object password to file"));
2114 com_err(me
, errno
, gettext("Error reading service object password file"));
2121 * Password entry for the service object is already present in the file
2122 * Delete the existing entry and add the new entry
2128 /* Create a new file with the extension .tmp */
2129 tmp_file
= (char *) malloc(sizeof(char) * (strlen(file_name
) + 4 + 1));
2130 if (tmp_file
== NULL
) {
2131 com_err(me
, ENOMEM
, gettext("while setting service object password"));
2135 sprintf(tmp_file
,"%s.%s",file_name
,"tmp");
2138 newfile
= fopen(tmp_file
, "wF");
2140 if (newfile
== NULL
) {
2141 com_err(me
, errno
, gettext("Error creating file %s"), tmp_file
);
2146 fseek(pfile
, 0, SEEK_SET
);
2147 while (fgets(line
, MAX_LEN
, pfile
) != NULL
) {
2148 if (((str
= strstr(line
, service_object
)) != NULL
) &&
2149 (line
[strlen(service_object
)] == '#')) {
2150 if (fprintf(newfile
, "%s#{HEX}%s\n", service_object
, hexpasswd
.data
) < 0) {
2151 com_err(me
, errno
, gettext("Failed to write service object password to file"));
2158 if (fprintf (newfile
, "%s", line
) < 0) {
2159 com_err(me
, errno
, gettext("Failed to write service object password to file"));
2169 com_err(me
, errno
, gettext("Error reading service object password file"));
2176 /* TODO: file lock for the service passowrd file */
2181 ret
= rename(tmp_file
, file_name
);
2183 com_err(me
, errno
, gettext("Failed to write service object password to "
2192 if (hexpasswd
.length
!= 0) {
2193 memset(hexpasswd
.data
, 0, hexpasswd
.length
);
2194 free(hexpasswd
.data
);
2198 free(service_object
);
2208 /* db_usage(STASH_SRV_PW); */
2214 #endif /* #ifdef HAVE_EDIRECTORY */