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 **) reallocarray(srvparams
->krbhostservers
,
692 (existing_entries
+ new_entries
+ 1),
694 if (temp_ptr
== NULL
) {
698 srvparams
->krbhostservers
= temp_ptr
;
700 list_modify_str_array(&(srvparams
->krbhostservers
),
701 (const char**)list
, LIST_MODE_ADD
);
707 srvparams
->krbhostservers
= list
;
709 out_mask
|= LDAP_SERVICE_HOSTSERVER
;
711 } else if (!strcmp(argv
[i
], "-realm")) {
715 if ((in_mask
& LDAP_SERVICE_REALMREFERENCE
) && (srvparams
->krbrealmreferences
)) {
717 /* Store the old realm list for removing rights */
718 oldrealmrefs
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
719 if (oldrealmrefs
== NULL
) {
724 for (j
= 0; srvparams
->krbrealmreferences
[j
] != NULL
; j
++) {
725 oldrealmrefs
[j
] = strdup(srvparams
->krbrealmreferences
[j
]);
726 if (oldrealmrefs
[j
] == NULL
) {
731 oldrealmrefs
[j
] = NULL
;
734 /* Free the old list if available */
735 krb5_free_list_entries (srvparams
->krbrealmreferences
);
736 free (srvparams
->krbrealmreferences
);
739 srvparams
->krbrealmreferences
= (char **)calloc(MAX_LIST_ENTRIES
,
741 if (srvparams
->krbrealmreferences
== NULL
) {
746 if ((retval
= krb5_parse_list(argv
[i
], LIST_DELIMITER
,
747 srvparams
->krbrealmreferences
))) {
751 /* Convert realm names to realm DNs */
752 if ((retval
= convert_realm_name2dn_list(
753 srvparams
->krbrealmreferences
,
754 ldap_context
->krbcontainer
->DN
))) {
758 out_mask
|= LDAP_SERVICE_REALMREFERENCE
;
760 /* Set flag to ignore 'add' and 'clear' */
762 } else if (!strcmp(argv
[i
], "-clearrealm")) {
767 /* If attribute doesn't exist, don't permit 'clear' option */
768 if (((in_mask
& LDAP_SERVICE_REALMREFERENCE
) == 0) || (srvparams
->krbrealmreferences
== NULL
)) {
769 /* Send out some proper error message here */
774 /* Store the old realm list for removing rights */
775 oldrealmrefs
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
776 if (oldrealmrefs
== NULL
) {
781 for (j
= 0; srvparams
->krbrealmreferences
[j
] != NULL
; j
++) {
782 oldrealmrefs
[j
] = strdup(srvparams
->krbrealmreferences
[j
]);
783 if (oldrealmrefs
[j
] == NULL
) {
788 oldrealmrefs
[j
] = NULL
;
791 /* Allocate list for processing */
792 list
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
798 if ((retval
= krb5_parse_list(argv
[i
], LIST_DELIMITER
, list
)))
801 /* Convert realm names to realm DNs */
802 if ((retval
= convert_realm_name2dn_list(list
,
803 ldap_context
->krbcontainer
->DN
))) {
807 list_modify_str_array(&(srvparams
->krbrealmreferences
),
808 (const char**)list
, LIST_MODE_DELETE
);
810 out_mask
|= LDAP_SERVICE_REALMREFERENCE
;
816 } else if (!strcmp(argv
[i
], "-addrealm")) {
821 /* Allocate list for processing */
822 list
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
828 if ((retval
= krb5_parse_list(argv
[i
], LIST_DELIMITER
, list
)))
831 /* Convert realm names to realm DNs */
832 if ((retval
= convert_realm_name2dn_list(list
,
833 ldap_context
->krbcontainer
->DN
))) {
837 if ((in_mask
& LDAP_SERVICE_REALMREFERENCE
) && (srvparams
->krbrealmreferences
) && (!oldrealmrefs
)) {
838 /* Store the old realm list for removing rights */
839 oldrealmrefs
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
840 if (oldrealmrefs
== NULL
) {
845 for (j
= 0; srvparams
->krbrealmreferences
[j
] != NULL
; j
++) {
846 oldrealmrefs
[j
] = strdup(srvparams
->krbrealmreferences
[j
]);
847 if (oldrealmrefs
[j
] == NULL
) {
852 oldrealmrefs
[j
] = NULL
;
855 /* Call list_modify_str_array() only if realm DN attribute
856 * exists already -- Actually, it's better to handle this
857 * within list_modify_str_array() */
858 if (in_mask
& LDAP_SERVICE_REALMREFERENCE
) {
859 /* Re-size existing list */
860 existing_entries
= list_count_str_array(
861 srvparams
->krbrealmreferences
);
862 new_entries
= list_count_str_array(list
);
863 temp_ptr
= (char **) reallocarray(srvparams
->krbrealmreferences
,
864 (existing_entries
+ new_entries
+ 1),
866 if (temp_ptr
== NULL
) {
870 srvparams
->krbrealmreferences
= temp_ptr
;
872 list_modify_str_array(&(srvparams
->krbrealmreferences
),
873 (const char**)list
, LIST_MODE_ADD
);
879 srvparams
->krbrealmreferences
= list
;
881 out_mask
|= LDAP_SERVICE_REALMREFERENCE
;
884 /* Any other argument must be service DN
889 /* Modify attributes of object */
890 if ((retval
= krb5_ldap_modify_service(util_context
, srvparams
, out_mask
)))
893 /* Service rights modification code */
894 if (out_mask
& LDAP_SERVICE_REALMREFERENCE
) {
896 printf("%s", gettext("Changing rights for the service object. Please wait ... "));
899 newrealmrefs
= (char**) calloc(MAX_LIST_ENTRIES
, sizeof(char*));
900 if (newrealmrefs
== NULL
) {
905 if ((srvparams
!= NULL
) && (srvparams
->krbrealmreferences
!= NULL
)) {
906 for (j
= 0; srvparams
->krbrealmreferences
[j
] != NULL
; j
++) {
907 newrealmrefs
[j
] = strdup(srvparams
->krbrealmreferences
[j
]);
908 if (newrealmrefs
[j
] == NULL
) {
913 newrealmrefs
[j
] = NULL
;
915 disjoint_members(oldrealmrefs
, newrealmrefs
);
917 /* Delete the rights for the given service, on each of the realm
918 * container & subtree in the old realm reference list.
922 rightsmask
|= LDAP_REALM_RIGHTS
;
923 rightsmask
|= LDAP_SUBTREE_RIGHTS
;
925 for (i
= 0; (oldrealmrefs
[i
] != NULL
); i
++) {
926 /* Get the realm name, not the dn */
927 temprdns
= ldap_explode_dn(oldrealmrefs
[i
], 1);
929 if (temprdns
[0] == NULL
) {
934 realmName
= strdup(temprdns
[0]);
935 if (realmName
== NULL
) {
940 if ((retval
= krb5_ldap_read_realm_params(util_context
,
941 realmName
, &rparams
, &rmask
))) {
942 com_err(me
, retval
, gettext("while reading information of realm '%s'"),
947 if ((retval
= krb5_ldap_delete_service_rights(util_context
,
948 srvparams
->servicetype
, srvparams
->servicedn
,
949 realmName
, rparams
->subtree
, rightsmask
))) {
950 printf(gettext("failed\n"));
951 com_err(me
, retval
, gettext("while assigning rights '%s'"),
952 srvparams
->servicedn
);
957 krb5_ldap_free_realm_params(rparams
);
961 /* Add the rights for the given service, on each of the realm
962 * container & subtree in the new realm reference list.
966 rightsmask
|= LDAP_REALM_RIGHTS
;
967 rightsmask
|= LDAP_SUBTREE_RIGHTS
;
969 for (i
= 0; (newrealmrefs
[i
] != NULL
); i
++) {
970 /* Get the realm name, not the dn */
971 temprdns
= ldap_explode_dn(newrealmrefs
[i
], 1);
973 if (temprdns
[0] == NULL
) {
978 realmName
= strdup(temprdns
[0]);
979 if (realmName
== NULL
) {
984 if ((retval
= krb5_ldap_read_krbcontainer_params(util_context
,
985 &(ldap_context
->krbcontainer
)))) {
987 gettext("while reading Kerberos container information"));
991 if ((retval
= krb5_ldap_read_realm_params(util_context
,
992 realmName
, &rparams
, &rmask
))) {
993 com_err(me
, retval
, gettext("while reading information of realm '%s'"),
998 if ((retval
= krb5_ldap_add_service_rights(util_context
,
999 srvparams
->servicetype
, srvparams
->servicedn
,
1000 realmName
, rparams
->subtree
, rightsmask
))) {
1001 printf(gettext("failed\n"));
1002 com_err(me
, retval
, gettext("while assigning rights '%s'"),
1003 srvparams
->servicedn
);
1008 krb5_ldap_free_realm_params(rparams
);
1012 printf(gettext("done\n"));
1024 /* Clean-up structure */
1025 krb5_ldap_free_service(util_context
, srvparams
);
1035 for (i
= 0; oldrealmrefs
[i
] != NULL
; i
++)
1036 free(oldrealmrefs
[i
]);
1041 for (i
= 0; newrealmrefs
[i
] != NULL
; i
++)
1042 free(newrealmrefs
[i
]);
1051 db_usage(MODIFY_SERVICE
);
1055 com_err(me
, retval
, gettext("while modifying service object"));
1064 * This function will delete the entry corresponding to the service object
1065 * from the service password file.
1067 static krb5_error_code
1068 rem_service_entry_from_file(argc
, argv
, file_name
, service_object
)
1072 char *service_object
;
1075 /* Solaris Kerberos */
1076 char *me
= progname
;
1077 char *tmp_file
= NULL
;
1080 unsigned int len
= 0;
1081 char line
[MAX_LEN
]={0};
1082 mode_t omask
= umask(077);
1084 /* Check for permissions on the password file */
1085 if (access(file_name
, W_OK
) == -1) {
1086 /* If the specified file itself is not there, no need to show error */
1087 if (errno
== ENOENT
) {
1091 com_err(me
, errno
, gettext("while deleting entry from file %s", file_name
));
1096 /* Create a temporary file which contains all the entries except the
1097 entry for the given service dn */
1098 pfile
= fopen(file_name
, "r+F");
1099 if (pfile
== NULL
) {
1100 com_err(me
, errno
, gettext("while deleting entry from file %s"), file_name
);
1104 /* Create a new file with the extension .tmp */
1105 tmp_file
= (char *)malloc(strlen(file_name
) + 4 + 1);
1106 if (tmp_file
== NULL
) {
1107 com_err(me
, ENOMEM
, gettext("while deleting entry from file"));
1111 snprintf (tmp_file
, strlen(file_name
) + 4 + 1, "%s%s", file_name
, ".tmp");
1114 tmpfd
= creat(tmp_file
, S_IRUSR
|S_IWUSR
);
1117 com_err(me
, errno
, gettext("while deleting entry from file\n"));
1122 /* Copy only those lines which donot have the specified service dn */
1123 while (fgets(line
, MAX_LEN
, pfile
) != NULL
) {
1124 if ((strstr(line
, service_object
) != NULL
) &&
1125 (line
[strlen(service_object
)] == '#')) {
1129 if (write(tmpfd
, line
, len
) != len
) {
1130 com_err(me
, errno
, gettext("while deleting entry from file\n"));
1140 if (unlink(file_name
) == 0) {
1141 link(tmp_file
, file_name
);
1143 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
);
1343 db_usage(VIEW_SERVICE
);
1351 * This function will list the DNs of kerberos services present on
1352 * the LDAP Server under a specific sub-tree (entire tree by default)
1354 void kdb5_ldap_list_services(argc
, argv
)
1358 /* Solaris Kerberos */
1359 char *me
= progname
;
1360 krb5_error_code retval
= 0;
1361 char *basedn
= NULL
;
1363 char **plist
= NULL
;
1364 krb5_boolean print_usage
= FALSE
;
1366 /* Check for number of arguments */
1367 if ((argc
!= 1) && (argc
!= 3)) {
1372 /* Parse base DN argument if present */
1374 if (strcmp(argv
[1], "-basedn")) {
1379 basedn
= strdup(argv
[2]);
1380 if (basedn
== NULL
) {
1381 com_err(me
, ENOMEM
, gettext("while listing services"));
1387 retval
= krb5_ldap_list_services(util_context
, basedn
, &list
);
1388 if ((retval
!= 0) || (list
== NULL
)) {
1393 for (plist
= list
; *plist
!= NULL
; plist
++) {
1394 printf("%s\n", *plist
);
1404 krb5_free_list_entries (list
);
1411 db_usage(LIST_SERVICE
);
1415 com_err(me
, retval
, gettext("while listing policy objects"));
1424 * This function will print the service object information
1425 * to the standard output
1428 print_service_params(lserparams
, mask
)
1429 krb5_ldap_service_params
*lserparams
;
1434 /* Print the service dn */
1435 printf("%20s%-20s\n", gettext("Service dn: "), lserparams
->servicedn
);
1437 /* Print the service type of the object to be read */
1438 if (lserparams
->servicetype
== LDAP_KDC_SERVICE
) {
1439 printf("%20s%-20s\n", gettext("Service type: "), "kdc");
1440 } else if (lserparams
->servicetype
== LDAP_ADMIN_SERVICE
) {
1441 printf("%20s%-20s\n", gettext("Service type: "), "admin");
1442 } else if (lserparams
->servicetype
== LDAP_PASSWD_SERVICE
) {
1443 printf("%20s%-20s\n", gettext("Service type: "), "pwd");
1446 /* Print the host server values */
1447 printf("%20s\n", gettext("Service host list: "));
1448 if (mask
& LDAP_SERVICE_HOSTSERVER
) {
1449 for (i
=0; lserparams
->krbhostservers
[i
] != NULL
; ++i
) {
1450 printf("%20s%-50s\n","",lserparams
->krbhostservers
[i
]);
1454 /* Print the realm reference dn values */
1455 printf("%20s\n", gettext("Realm DN list: "));
1456 if (mask
& LDAP_SERVICE_REALMREFERENCE
) {
1457 for (i
=0; lserparams
&& lserparams
->krbrealmreferences
&& lserparams
->krbrealmreferences
[i
] != NULL
; ++i
) {
1458 printf("%20s%-50s\n","",lserparams
->krbrealmreferences
[i
]);
1467 * This function will generate random password of length(RANDOM_PASSWD_LEN)
1474 * RANDOM_PASSWD_LEN length random password
1476 static int generate_random_password(krb5_context ctxt
, char **randpwd
, unsigned int *passlen
)
1478 char *random_pwd
= NULL
;
1484 /* setting random password length in the range 16-32 */
1485 srand((unsigned int)(time(0) ^ getpid()));
1487 data
.length
= RANDOM_PASSWD_LEN
;
1488 random_pwd
= (char *)malloc(data
.length
+ 1);
1489 if (random_pwd
== NULL
) {
1490 com_err("setsrvpw", ENOMEM
, gettext("while generating random password"));
1493 memset(random_pwd
, 0, data
.length
+ 1);
1494 data
.data
= random_pwd
;
1496 ret
= krb5_c_random_make_octets(ctxt
, &data
);
1498 com_err("setsrvpw", ret
, gettext("Error generating random password"));
1503 for (i
=0; i
<data
.length
; i
++) {
1504 /* restricting to ascii chars. Need to change this when 8.8 supports */
1505 if ((unsigned char)random_pwd
[i
] > 127) {
1506 random_pwd
[i
] = (unsigned char)random_pwd
[i
] % 128;
1507 } else if (random_pwd
[i
] == 0) {
1508 random_pwd
[i
] = (rand()/(RAND_MAX
/127 + 1))+1;
1512 *randpwd
= random_pwd
;
1513 *passlen
= data
.length
;
1520 * This function will set the password of the service object in the directory
1521 * and/or the specified service password file.
1525 * argc - contains the number of arguments for this sub-command
1526 * argv - array of arguments for this sub-command
1532 kdb5_ldap_set_service_password(argc
, argv
)
1536 krb5_ldap_context
*lparams
= NULL
;
1537 char *file_name
= NULL
;
1538 char *tmp_file
= NULL
;
1539 /* Solaris Kerberos */
1540 char *me
= progname
;
1542 int random_passwd
= 0;
1543 int set_dir_pwd
= 1;
1544 krb5_boolean db_init_local
= FALSE
;
1545 char *service_object
= NULL
;
1546 char *passwd
= NULL
;
1547 char *prompt1
= NULL
;
1548 char *prompt2
= NULL
;
1549 unsigned int passwd_len
= 0;
1550 krb5_error_code errcode
= -1;
1551 int retval
= 0, i
= 0;
1552 unsigned int len
= 0;
1553 krb5_boolean print_usage
= FALSE
;
1557 kdb5_dal_handle
*dal_handle
= NULL
;
1558 struct data encrypted_passwd
= {0, NULL
};
1560 /* The arguments for setsrv password should contain the service object DN
1561 * and options to specify whether the password should be updated in file only
1562 * or both file and directory. So the possible combination of arguments are:
1563 * setsrvpw servicedn wherein argc is 2
1564 * setsrvpw -fileonly servicedn wherein argc is 3
1565 * setsrvpw -randpw servicedn wherein argc is 3
1566 * setsrvpw -f filename servicedn wherein argc is 4
1567 * setsrvpw -fileonly -f filename servicedn wherein argc is 5
1568 * setsrvpw -randpw -f filename servicedn wherein argc is 5
1570 if ((argc
< 2) || (argc
> 5)) {
1575 dal_handle
= (kdb5_dal_handle
*)util_context
->db_context
;
1576 lparams
= (krb5_ldap_context
*) dal_handle
->db_context
;
1578 if (lparams
== NULL
) {
1579 printf(gettext("%s: Invalid LDAP handle\n"), me
);
1583 /* Parse the arguments */
1584 for (i
= 1; i
< argc
-1 ; i
++) {
1585 if (strcmp(argv
[i
], "-randpw") == 0) {
1587 } else if (strcmp(argv
[i
], "-fileonly") == 0) {
1589 } else if (strcmp(argv
[i
], "-f") == 0) {
1590 if (argv
[++i
] == NULL
) {
1595 file_name
= strdup(argv
[i
]);
1596 if (file_name
== NULL
) {
1597 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1600 /* Verify if the file location has the proper file name
1601 * for eg, if the file location is a directory like /home/temp/,
1604 filelen
= strlen(file_name
);
1605 if ((filelen
== 0) || (file_name
[filelen
-1] == '/')) {
1606 printf(gettext("%s: Filename not specified for setting service object password\n"), me
);
1611 printf(gettext("%s: Invalid option specified for \"setsrvpw\" command\n"), me
);
1622 service_object
= strdup(argv
[i
]);
1623 if (service_object
== NULL
) {
1624 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1628 if (strlen(service_object
) == 0) {
1629 printf(gettext("%s: Service object not specified for \"setsrvpw\" command\n"), me
);
1634 if (service_object
[0] == '-') {
1639 if (file_name
== NULL
) {
1640 file_name
= strdup(DEF_SERVICE_PASSWD_FILE
);
1641 if (file_name
== NULL
) {
1642 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1648 if (db_inited
== FALSE
) {
1649 if ((errcode
= krb5_ldap_db_init(util_context
, lparams
))) {
1650 com_err(me
, errcode
, gettext("while initializing database"));
1653 db_init_local
= TRUE
;
1657 if (random_passwd
) {
1659 printf(gettext("%s: Invalid option specified for \"setsrvpw\" command\n"), me
);
1663 /* Generate random password */
1665 if ((errcode
= generate_random_password(util_context
, &passwd
, &passwd_len
))) {
1666 printf(gettext("%s: Failed to set service object password\n"), me
);
1669 passwd_len
= strlen(passwd
);
1672 /* Get the service object password from the terminal */
1673 passwd
= (char *)malloc(MAX_SERVICE_PASSWD_LEN
+ 1);
1674 if (passwd
== NULL
) {
1675 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1678 memset(passwd
, 0, MAX_SERVICE_PASSWD_LEN
+ 1);
1679 passwd_len
= MAX_SERVICE_PASSWD_LEN
;
1681 len
= strlen(service_object
);
1682 /* size of allocation=strlen of servicedn + strlen("Password for \" \"")=20 */
1683 prompt1
= (char *)malloc(len
+ 20);
1684 if (prompt1
== NULL
) {
1685 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1688 sprintf(prompt1
, gettext("Password for \"%s\""), service_object
);
1690 /* size of allocation=strlen of servicedn + strlen("Re-enter Password for \" \"")=30 */
1691 prompt2
= (char *)malloc(len
+ 30);
1692 if (prompt2
== NULL
) {
1693 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1697 sprintf(prompt2
, gettext("Re-enter password for \"%s\""), service_object
);
1699 retval
= krb5_read_password(util_context
, prompt1
, prompt2
, passwd
, &passwd_len
);
1703 com_err(me
, retval
, gettext("while setting service object password"));
1704 memset(passwd
, 0, MAX_SERVICE_PASSWD_LEN
);
1707 if (passwd_len
== 0) {
1708 printf(gettext("%s: Invalid password\n"), me
);
1709 memset(passwd
, 0, MAX_SERVICE_PASSWD_LEN
);
1712 passwd_len
= strlen(passwd
);
1715 /* Hex the password */
1718 pwd
.length
= passwd_len
;
1721 errcode
= tohex(pwd
, &hex
);
1723 if (hex
.length
!= 0) {
1724 memset(hex
.data
, 0, hex
.length
);
1727 com_err(me
, errcode
, gettext("Failed to convert the password to hex"));
1728 memset(passwd
, 0, passwd_len
);
1731 /* Password = {CRYPT}<encrypted password>:<encrypted key> */
1732 encrypted_passwd
.value
= (unsigned char *)malloc(strlen(service_object
) +
1733 1 + 5 + hex
.length
+ 2);
1734 if (encrypted_passwd
.value
== NULL
) {
1735 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1736 memset(passwd
, 0, passwd_len
);
1737 memset(hex
.data
, 0, hex
.length
);
1741 encrypted_passwd
.value
[strlen(service_object
) +
1742 1 + 5 + hex
.length
+ 1] = '\0';
1743 sprintf((char *)encrypted_passwd
.value
, "%s#{HEX}%s\n", service_object
, hex
.data
);
1744 encrypted_passwd
.len
= strlen((char *)encrypted_passwd
.value
);
1745 memset(hex
.data
, 0, hex
.length
);
1749 /* We should check if the file exists and we have permission to write into that file */
1750 if (access(file_name
, W_OK
) == -1) {
1751 if (errno
== ENOENT
) {
1755 printf(gettext("File does not exist. Creating the file %s...\n"), file_name
);
1757 fd
= creat(file_name
, S_IRUSR
|S_IWUSR
);
1760 com_err(me
, errno
, gettext("Error creating file %s"), file_name
);
1761 memset(passwd
, 0, passwd_len
);
1766 com_err(me
, errno
, gettext("Unable to access the file %s"), file_name
);
1767 memset(passwd
, 0, passwd_len
);
1773 if ((errcode
= krb5_ldap_set_service_passwd(util_context
, service_object
, passwd
)) != 0) {
1774 com_err(me
, errcode
, gettext("Failed to set password for service object %s"), service_object
);
1775 memset(passwd
, 0, passwd_len
);
1780 memset(passwd
, 0, passwd_len
);
1783 /* TODO: file lock for the service password file */
1784 /* set password in the file */
1785 pfile
= fopen(file_name
, "r+F");
1786 if (pfile
== NULL
) {
1787 com_err(me
, errno
, gettext("Failed to open file %s"), file_name
);
1791 while (fgets(line
, MAX_LEN
, pfile
) != NULL
) {
1792 if ((str
= strstr(line
, service_object
)) != NULL
) {
1793 if (line
[strlen(service_object
)] == '#') {
1801 /* If the service object dn is not present in the service password file */
1802 if (fwrite(encrypted_passwd
.value
, (unsigned int)encrypted_passwd
.len
, 1, pfile
) != 1) {
1803 com_err(me
, errno
, gettext("Failed to write service object password to file"));
1807 com_err(me
, errno
, gettext("Error reading service object password file"));
1813 /* Password entry for the service object is already present in the file */
1814 /* Delete the existing entry and add the new entry */
1815 FILE *newfile
= NULL
;
1818 /* Create a new file with the extension .tmp */
1819 tmp_file
= (char *) malloc(sizeof(char) * (strlen(file_name
) + 4 + 1));
1820 if (tmp_file
== NULL
) {
1821 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1824 sprintf(tmp_file
,"%s.%s",file_name
,"tmp");
1827 newfile
= fopen(tmp_file
, "w+F");
1829 if (newfile
== NULL
) {
1830 com_err(me
, errno
, gettext("Error creating file %s"), tmp_file
);
1835 fseek(pfile
, 0, SEEK_SET
);
1836 while (fgets(line
, MAX_LEN
, pfile
) != NULL
) {
1837 if (((str
= strstr(line
, service_object
)) != NULL
) && (line
[strlen(service_object
)] == '#')) {
1838 if (fprintf(newfile
, "%s", encrypted_passwd
.value
) < 0) {
1839 com_err(me
, errno
, gettext("Failed to write service object password to file"));
1846 if (fprintf(newfile
, "%s", line
) < 0) {
1847 com_err(me
, errno
, gettext("Failed to write service object password to file"));
1856 com_err(me
, errno
, gettext("Error reading service object password file"));
1862 /* TODO: file lock for the service password file */
1869 if (unlink(file_name
) == 0) {
1870 link(tmp_file
, file_name
);
1872 com_err(me
, errno
, gettext("Failed to write service object password to file"));
1882 krb5_ldap_close(util_context
);
1884 free(service_object
);
1890 if (encrypted_passwd
.value
) {
1891 memset(encrypted_passwd
.value
, 0, encrypted_passwd
.len
);
1892 free(encrypted_passwd
.value
);
1901 db_usage(SET_SRV_PW
);
1906 #else /* #ifdef HAVE_EDIRECTORY */
1909 * Convert the user supplied password into hexadecimal and stash it. Only a
1910 * little more secure than storing plain password in the file ...
1913 kdb5_ldap_stash_service_password(argc
, argv
)
1918 unsigned int passwd_len
= 0;
1919 /* Solaris Kerberos */
1920 char *me
= progname
;
1921 char *service_object
= NULL
;
1922 char *file_name
= NULL
, *tmp_file
= NULL
;
1923 char passwd
[MAX_SERVICE_PASSWD_LEN
];
1928 krb5_boolean print_usage
= FALSE
;
1929 krb5_data hexpasswd
= {0, 0, NULL
};
1930 mode_t old_mode
= 0;
1934 * stashsrvpw [-f filename] service_dn
1936 * 'service_dn' is the DN of the service object
1937 * 'filename' is the path of the stash file
1939 if (argc
!= 2 && argc
!= 4) {
1945 /* Find the stash file name */
1946 if (strcmp (argv
[1], "-f") == 0) {
1947 if (((file_name
= strdup (argv
[2])) == NULL
) ||
1948 ((service_object
= strdup (argv
[3])) == NULL
)) {
1949 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1952 } else if (strcmp (argv
[2], "-f") == 0) {
1953 if (((file_name
= strdup (argv
[3])) == NULL
) ||
1954 ((service_object
= strdup (argv
[1])) == NULL
)) {
1955 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1962 if (file_name
== NULL
) {
1963 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1966 } else { /* argc == 2 */
1969 service_object
= strdup (argv
[1]);
1970 if (service_object
== NULL
) {
1971 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1975 /* Pick up the stash-file name from krb5.conf */
1976 profile_get_string(util_context
->profile
, KDB_REALM_SECTION
,
1977 util_context
->default_realm
, KDB_MODULE_POINTER
, NULL
, §ion
);
1979 if (section
== NULL
) {
1980 profile_get_string(util_context
->profile
, KDB_MODULE_DEF_SECTION
,
1981 KDB_MODULE_POINTER
, NULL
, NULL
, §ion
);
1982 if (section
== NULL
) {
1983 /* Stash file path neither in krb5.conf nor on command line */
1984 file_name
= strdup(DEF_SERVICE_PASSWD_FILE
);
1985 if (file_name
== NULL
) {
1986 com_err(me
, ENOMEM
, gettext("while setting service object password"));
1993 profile_get_string (util_context
->profile
, KDB_MODULE_SECTION
, section
,
1994 "ldap_service_password_file", NULL
, &file_name
);
1997 * Solaris Kerberos: use default if ldap_service_password_file not set
1999 if (file_name
== NULL
) {
2000 file_name
= strdup(DEF_SERVICE_PASSWD_FILE
);
2001 if (file_name
== NULL
) {
2002 com_err(me
, ENOMEM
, gettext("while setting service object password"));
2009 /* Get password from user */
2011 char prompt1
[256], prompt2
[256];
2013 /* Get the service object password from the terminal */
2014 memset(passwd
, 0, sizeof (passwd
));
2015 passwd_len
= sizeof (passwd
);
2017 /* size of prompt = strlen of servicedn + strlen("Password for \" \"") */
2018 assert (sizeof (prompt1
) > (strlen (service_object
)
2019 + sizeof ("Password for \" \"")));
2020 sprintf(prompt1
, gettext("Password for \"%s\""), service_object
);
2022 /* size of prompt = strlen of servicedn + strlen("Re-enter Password for \" \"") */
2023 assert (sizeof (prompt2
) > (strlen (service_object
)
2024 + sizeof ("Re-enter Password for \" \"")));
2025 sprintf(prompt2
, gettext("Re-enter password for \"%s\""), service_object
);
2027 ret
= krb5_read_password(util_context
, prompt1
, prompt2
, passwd
, &passwd_len
);
2029 com_err(me
, ret
, gettext("while setting service object password"));
2030 memset(passwd
, 0, sizeof (passwd
));
2034 if (passwd_len
== 0) {
2035 printf(gettext("%s: Invalid password\n"), me
);
2036 memset(passwd
, 0, MAX_SERVICE_PASSWD_LEN
);
2041 /* Convert the password to hexadecimal */
2045 pwd
.length
= passwd_len
;
2048 ret
= tohex(pwd
, &hexpasswd
);
2050 com_err(me
, ret
, gettext("Failed to convert the password to hexadecimal"));
2051 memset(passwd
, 0, passwd_len
);
2055 memset(passwd
, 0, passwd_len
);
2057 /* TODO: file lock for the service passowrd file */
2059 /* set password in the file */
2060 #if 0 /* ************ Begin IFDEF'ed OUT ***************************** */
2061 old_mode
= umask(0177);
2062 pfile
= fopen(file_name
, "a+");
2063 if (pfile
== NULL
) {
2064 com_err(me
, errno
, gettext("Failed to open file %s: %s"), file_name
,
2071 /* Solaris Kerberos: safer than the above */
2072 fd
= open(file_name
, O_CREAT
|O_RDWR
|O_APPEND
, 0600);
2074 com_err(me
, errno
, gettext("Failed to open file %s: %s"), file_name
,
2078 pfile
= fdopen(fd
, "a+F");
2079 if (pfile
== NULL
) {
2080 com_err(me
, errno
, gettext("Failed to open file %s: %s"), file_name
,
2087 while (fgets (line
, MAX_LEN
, pfile
) != NULL
) {
2088 if ((str
= strstr (line
, service_object
)) != NULL
) {
2090 * White spaces not allowed, # delimits the service dn from the
2093 if (line
[strlen (service_object
)] == '#')
2101 /* If the service object dn is not present in the service password file */
2102 if (fprintf(pfile
, "%s#{HEX}%s\n", service_object
, hexpasswd
.data
) < 0) {
2103 com_err(me
, errno
, gettext("Failed to write service object password to file"));
2108 com_err(me
, errno
, gettext("Error reading service object password file"));
2115 * Password entry for the service object is already present in the file
2116 * Delete the existing entry and add the new entry
2122 /* Create a new file with the extension .tmp */
2123 tmp_file
= (char *) malloc(sizeof(char) * (strlen(file_name
) + 4 + 1));
2124 if (tmp_file
== NULL
) {
2125 com_err(me
, ENOMEM
, gettext("while setting service object password"));
2129 sprintf(tmp_file
,"%s.%s",file_name
,"tmp");
2132 newfile
= fopen(tmp_file
, "wF");
2134 if (newfile
== NULL
) {
2135 com_err(me
, errno
, gettext("Error creating file %s"), tmp_file
);
2140 fseek(pfile
, 0, SEEK_SET
);
2141 while (fgets(line
, MAX_LEN
, pfile
) != NULL
) {
2142 if (((str
= strstr(line
, service_object
)) != NULL
) &&
2143 (line
[strlen(service_object
)] == '#')) {
2144 if (fprintf(newfile
, "%s#{HEX}%s\n", service_object
, hexpasswd
.data
) < 0) {
2145 com_err(me
, errno
, gettext("Failed to write service object password to file"));
2152 if (fprintf (newfile
, "%s", line
) < 0) {
2153 com_err(me
, errno
, gettext("Failed to write service object password to file"));
2163 com_err(me
, errno
, gettext("Error reading service object password file"));
2170 /* TODO: file lock for the service passowrd file */
2175 ret
= rename(tmp_file
, file_name
);
2177 com_err(me
, errno
, gettext("Failed to write service object password to "
2186 if (hexpasswd
.length
!= 0) {
2187 memset(hexpasswd
.data
, 0, hexpasswd
.length
);
2188 free(hexpasswd
.data
);
2191 free(service_object
);
2199 /* db_usage(STASH_SRV_PW); */
2205 #endif /* #ifdef HAVE_EDIRECTORY */