/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
*/
/* Copyright (c) 2004-2005, Novell, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* * The copyright holder's name is not used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Create / Delete / Modify / View / List service objects.
*/
/*
* Service objects have rights over realm objects and principals. The following
* functions manage the service objects.
*/
#include <stdio.h>
#include <k5-int.h>
#include <libintl.h> /* Solaris Kerberos */
#include <locale.h> /* Solaris Kerberos */
#include "kdb5_ldap_util.h"
#include "kdb5_ldap_list.h"
#ifdef HAVE_EDIRECTORY
char *argv[],
char *file_name,
char *service_object);
extern char *yes;
extern krb5_boolean db_inited;
{
char host_str[MAX_LEN_LIST_ENTRY] = "", proto_str[PROTOCOL_STR_LEN + 1] = "", port_str[PORT_STR_LEN + 1] = "";
int j = 0;
/* Protocol and port number processing */
for (j = 0; host_list[j]; j++) {
/* Look for one hash */
/* Check input for buffer overflow */
if (hostname_len >= MAX_LEN_LIST_ENTRY) {
goto cleanup;
}
/* First copy off the host name portion */
/* Parse for the protocol string and translate to number */
else
/* Look for one more hash */
/* Parse for the port string and check if it is numeric */
port_str[0] = '\0';
} else
port_str[0] = '\0';
} else { /* We have only host name */
proto_str[0] = '\0';
port_str[0] = '\0';
}
/* Now, based on service type, fill in suitable protocol
and port values if they are absent or not matching */
if (servicetype == LDAP_KDC_SERVICE) {
if (proto_str[0] == '\0')
if (port_str[0] == '\0')
} else if (servicetype == LDAP_ADMIN_SERVICE) {
if (proto_str[0] == '\0')
/* Print warning message */
}
if (port_str[0] == '\0')
} else if (servicetype == LDAP_PASSWD_SERVICE) {
if (proto_str[0] == '\0')
/* Print warning message */
}
if (port_str[0] == '\0')
}
/* Finally form back the string */
goto cleanup;
}
}
return retval;
}
/*
* Given a realm name, this function will convert it to a DN by appending the
* Kerberos container location.
*/
static krb5_error_code
char **list;
const char *krbcontainer_loc;
{
int i = 0;
return EINVAL;
}
/* Restrict copying to max. length to avoid buffer overflow */
/* Make copy of string to temporary node */
goto cleanup;
}
/* On success, free list node and attach new one */
}
return retval;
}
/*
* This function will create a service object on the LDAP Server, with the
* specified attributes.
*/
int argc;
char *argv[];
{
/* Solaris Kerberos */
int mask = 0;
int extra_argc = 0;
int i = 0;
int rmask = 0;
int rightsmask =0;
/* Check for number of arguments */
exit_status++;
goto err_usage;
}
/* Allocate memory for service parameters structure */
goto cleanup;
}
/* Allocate memory for extra arguments to be used for setting
password -- it's OK to allocate as much as the total number
of arguments */
if (extra_argv == NULL) {
goto cleanup;
}
/* Set first of the extra arguments as the program name */
extra_argv[0] = me;
extra_argc++;
/* Read Kerberos container info, to construct realm DN from name
* and for assigning rights
*/
&(ldap_context->krbcontainer)))) {
goto cleanup;
}
/* Parse all arguments */
for (i = 1; i < argc; i++) {
if (++i > argc - 1)
goto err_usage;
sizeof(char *));
goto cleanup;
}
srvparams->krbhostservers))) {
goto cleanup;
}
srvparams->servicetype))) {
goto cleanup;
}
if (++i > argc - 1)
goto err_usage;
sizeof(char *));
goto cleanup;
}
srvparams->krbrealmreferences))) {
goto cleanup;
}
/* Convert realm names to realm DNs */
if ((retval = convert_realm_name2dn_list(
goto cleanup;
}
}
/* If argument is none of the above and beginning with '-',
* it must be related to password -- collect it
* to pass onto kdb5_ldap_set_service_password()
*/
else if (*(argv[i]) == '-') {
/* Checking for options of setting the password for the
* service (by using 'setsrvpw') is not modular. --need to
* have a common function that can be shared with 'setsrvpw'
*/
extra_argc++;
extra_argc++;
}
/* For '-f' option alone, pick up the following argument too */
extra_argc++;
if (++i > argc - 1)
goto err_usage;
extra_argc++;
} else { /* Any other option is invalid */
exit_status++;
goto err_usage;
}
} else { /* Any other argument must be service DN */
/* First check if service DN is already provided --
* if so, there's a usage error
*/
goto err_usage;
}
/* If not present already, fill up service DN */
goto err_nomsg;
}
}
}
/* No point in proceeding further if service DN value is not available */
goto err_usage;
}
goto err_usage;
}
/* Create object with all attributes provided */
goto cleanup;
/* ** NOTE ** srvparams structure should not be modified, as it is
* used for deletion of the service object in case of any failures
* from now on.
*/
/* Set password too */
if (extra_argc >= 1) {
/* Set service DN as the last argument */
goto cleanup;
}
extra_argc++;
goto err_nomsg;
}
}
/* Rights assignment */
if (mask & LDAP_SERVICE_REALMREFERENCE) {
rightsmask =0;
/* Get the realm name, not the dn */
goto cleanup;
}
goto cleanup;
}
goto cleanup;
}
goto cleanup;
}
if (rparams)
}
}
}
goto cleanup;
print_usage = TRUE;
/* This is for deleting the service object if something goes
* wrong in creating the service object
*/
/* srvparams is populated from the user input and should be correct as
* we were successful in creating a service object. Reusing the same
*/
}
/* Clean-up structure */
if (extra_argv) {
free (extra_argv);
extra_argv = NULL;
}
if (realmName) {
}
if (print_usage)
if (retval) {
if (!no_msg)
exit_status++;
}
return;
}
/*
* This function will modify the attributes of a given service
* object on the LDAP Server
*/
int argc;
char *argv[];
{
/* Solaris Kerberos */
int i = 0;
int j = 0;
int rmask = 0;
int rightsmask =0;
/* Check for number of arguments */
exit_status++;
goto err_usage;
}
/* Parse all arguments, only to pick up service DN (Pass 1) */
for (i = 1; i < argc; i++) {
/* Skip arguments next to 'servicehost'
and 'realmdn' arguments */
++i;
++i;
++i;
++i;
++i;
++i;
} else { /* Any other argument must be service DN */
/* First check if service DN is already provided --
if so, there's a usage error */
goto err_usage;
}
/* If not present already, fill up service DN */
goto err_nomsg;
}
}
}
/* No point in proceeding further if service DN value is not available */
goto err_usage;
}
if (retval) {
/* Solaris Kerberos */
goto err_nomsg;
}
/* Read Kerberos container info, to construct realm DN from name
* and for assigning rights
*/
&(ldap_context->krbcontainer)))) {
goto cleanup;
}
/* Parse all arguments, but skip the service DN (Pass 2) */
for (i = 1; i < argc; i++) {
if (++i > argc - 1)
goto err_usage;
/* Free the old list if available */
if (srvparams->krbhostservers) {
}
sizeof(char *));
goto cleanup;
}
srvparams->krbhostservers))) {
goto cleanup;
}
srvparams->servicetype))) {
goto cleanup;
}
/* Set flag to ignore 'add' and 'clear' */
srvhost_flag = 1;
if (++i > argc - 1)
goto err_usage;
if (!srvhost_flag) {
/* If attribute doesn't exist, don't permit 'clear' option */
if ((in_mask & LDAP_SERVICE_HOSTSERVER) == 0) {
/* Send out some proper error message here */
goto err_nomsg;
}
/* Allocate list for processing */
goto cleanup;
}
goto cleanup;
goto cleanup;
}
(const char**)list, LIST_MODE_DELETE);
/* Clean up */
}
if (++i > argc - 1)
goto err_usage;
if (!srvhost_flag) {
/* Allocate list for processing */
goto cleanup;
}
goto cleanup;
goto cleanup;
}
/* Call list_modify_str_array() only if host server attribute
* exists already --Actually, it's better to handle this
* within list_modify_str_array()
*/
if (in_mask & LDAP_SERVICE_HOSTSERVER) {
/* Re-size existing list */
goto cleanup;
}
(const char**)list, LIST_MODE_ADD);
/* Clean up */
} else
}
if (++i > argc - 1)
goto err_usage;
if (!oldrealmrefs) {
/* Store the old realm list for removing rights */
if (oldrealmrefs == NULL) {
goto cleanup;
}
if (oldrealmrefs[j] == NULL) {
goto cleanup;
}
}
oldrealmrefs[j] = NULL;
}
/* Free the old list if available */
}
sizeof(char *));
goto cleanup;
}
srvparams->krbrealmreferences))) {
goto cleanup;
}
/* Convert realm names to realm DNs */
if ((retval = convert_realm_name2dn_list(
goto cleanup;
}
/* Set flag to ignore 'add' and 'clear' */
realmdn_flag = 1;
if (++i > argc - 1)
goto err_usage;
if (!realmdn_flag) {
/* If attribute doesn't exist, don't permit 'clear' option */
/* Send out some proper error message here */
goto err_nomsg;
}
if (!oldrealmrefs) {
/* Store the old realm list for removing rights */
if (oldrealmrefs == NULL) {
goto cleanup;
}
if (oldrealmrefs[j] == NULL) {
goto cleanup;
}
}
oldrealmrefs[j] = NULL;
}
/* Allocate list for processing */
goto cleanup;
}
goto cleanup;
/* Convert realm names to realm DNs */
goto cleanup;
}
(const char**)list, LIST_MODE_DELETE);
/* Clean up */
}
if (++i > argc - 1)
goto err_usage;
if (!realmdn_flag) {
/* Allocate list for processing */
goto cleanup;
}
goto cleanup;
/* Convert realm names to realm DNs */
goto cleanup;
}
if ((in_mask & LDAP_SERVICE_REALMREFERENCE) && (srvparams->krbrealmreferences) && (!oldrealmrefs)) {
/* Store the old realm list for removing rights */
if (oldrealmrefs == NULL) {
goto cleanup;
}
if (oldrealmrefs[j] == NULL) {
goto cleanup;
}
}
oldrealmrefs[j] = NULL;
}
/* Call list_modify_str_array() only if realm DN attribute
* exists already -- Actually, it's better to handle this
* within list_modify_str_array() */
if (in_mask & LDAP_SERVICE_REALMREFERENCE) {
/* Re-size existing list */
goto cleanup;
}
(const char**)list, LIST_MODE_ADD);
/* Clean up */
} else
}
} else {
/* Any other argument must be service DN
-- skip it */
}
}
/* Modify attributes of object */
goto cleanup;
/* Service rights modification code */
if (out_mask & LDAP_SERVICE_REALMREFERENCE) {
if (newrealmrefs == NULL) {
goto cleanup;
}
if (newrealmrefs[j] == NULL) {
goto cleanup;
}
}
newrealmrefs[j] = NULL;
}
/* Delete the rights for the given service, on each of the realm
* container & subtree in the old realm reference list.
*/
if (oldrealmrefs) {
rightsmask = 0;
for (i = 0; (oldrealmrefs[i] != NULL); i++) {
/* Get the realm name, not the dn */
goto cleanup;
}
goto cleanup;
}
goto err_nomsg;
}
goto err_nomsg;
}
if (rparams)
}
}
/* Add the rights for the given service, on each of the realm
* container & subtree in the new realm reference list.
*/
if (newrealmrefs) {
rightsmask = 0;
for (i = 0; (newrealmrefs[i] != NULL); i++) {
/* Get the realm name, not the dn */
goto cleanup;
}
goto cleanup;
}
&(ldap_context->krbcontainer)))) {
gettext("while reading Kerberos container information"));
goto cleanup;
}
goto err_nomsg;
}
goto err_nomsg;
}
if (rparams) {
}
}
}
}
goto cleanup;
print_usage = TRUE;
/* Clean-up structure */
if (servicedn)
if (list) {
}
if (oldrealmrefs) {
for (i = 0; oldrealmrefs[i] != NULL; i++)
free(oldrealmrefs[i]);
}
if (newrealmrefs) {
for (i = 0; newrealmrefs[i] != NULL; i++)
free(newrealmrefs[i]);
}
if (realmName) {
}
if (print_usage)
if (retval) {
if (!no_msg)
exit_status++;
}
return;
}
/*
* This function will delete the entry corresponding to the service object
* from the service password file.
*/
static krb5_error_code
int argc;
char *argv[];
char *file_name;
char *service_object;
{
/* Solaris Kerberos */
unsigned int len = 0;
/* Check for permissions on the password file */
/* If the specified file itself is not there, no need to show error */
st=0;
goto cleanup;
} else {
goto cleanup;
}
}
/* Create a temporary file which contains all the entries except the
entry for the given service dn */
goto cleanup;
}
/* Create a new file with the extension .tmp */
goto cleanup;
}
if (tmpfd == -1) {
goto cleanup;
}
/* Copy only those lines which donot have the specified service dn */
continue;
} else {
goto cleanup;
}
}
}
} else {
}
st=0;
if (tmp_file)
return st;
}
/*
* This function will delete the service object from the LDAP Server
* and unlink the references to the Realm objects (if any)
*/
void
int argc;
char *argv[];
{
int i = 0;
int force = 0;
int mask = 0;
exit_status++;
goto err_usage;
}
for (i=1; i < argc; i++) {
force++;
if (argv[i+1]) {
if (stashfilename == NULL) {
/* Solaris Kerberos */
exit_status++;
goto cleanup;
}
i++;
} else {
exit_status++;
goto err_usage;
}
} else {
/* Solaris Kerberos */
exit_status++;
goto cleanup;
}
} else {
exit_status++;
goto err_usage;
}
}
}
if (!servicedn) {
exit_status++;
goto err_usage;
}
if (!force) {
exit_status++;
goto cleanup;;
}
exit_status++;
goto cleanup;
}
}
&lserparams, &mask))) {
/* Solaris Kerberos */
exit_status++;
goto cleanup;
}
if (retval) {
/* Solaris Kerberos */
exit_status++;
goto cleanup;
}
if (stashfilename == NULL) {
if (stashfilename == NULL) {
/* Solaris Kerberos */
exit_status++;
goto cleanup;
}
}
if (retval)
goto cleanup;
print_usage = TRUE;
if (lserparams) {
}
if (servicedn) {
}
if (stashfilename) {
}
if (print_usage) {
}
return;
}
/*
* This function will display information about the given service object
*/
int argc;
char *argv[];
{
int mask = 0;
if (!(argc == 2)) {
exit_status++;
goto err_usage;
}
/* Solaris Kerberos */
exit_status++;
goto cleanup;
}
/* Solaris Kerberos */
exit_status++;
goto cleanup;
}
goto cleanup;
print_usage = TRUE;
if (lserparams) {
}
if (servicedn)
if (print_usage) {
}
return;
}
/*
* This function will list the DNs of kerberos services present on
* the LDAP Server under a specific sub-tree (entire tree by default)
*/
int argc;
char *argv[];
{
/* Solaris Kerberos */
/* Check for number of arguments */
exit_status++;
goto err_usage;
}
/* Parse base DN argument if present */
if (argc == 3) {
goto err_usage;
}
exit_status++;
goto cleanup;
}
}
exit_status++;
goto cleanup;
}
}
goto cleanup;
print_usage = TRUE;
}
if (basedn)
if (print_usage) {
}
if (retval) {
exit_status++;
}
return;
}
/*
* This function will print the service object information
* to the standard output
*/
static void
int mask;
{
int i=0;
/* Print the service dn */
/* Print the service type of the object to be read */
}
/* Print the host server values */
if (mask & LDAP_SERVICE_HOSTSERVER) {
}
}
/* Print the realm reference dn values */
if (mask & LDAP_SERVICE_REALMREFERENCE) {
for (i=0; lserparams && lserparams->krbrealmreferences && lserparams->krbrealmreferences[i] != NULL; ++i) {
}
}
return;
}
/*
* This function will generate random password of length(RANDOM_PASSWD_LEN)
*
*
* INPUT:
* ctxt - context
*
* OUTPUT:
* RANDOM_PASSWD_LEN length random password
*/
{
int ret = 0;
int i=0;
/*int len = 0;*/
/* setting random password length in the range 16-32 */
if (random_pwd == NULL) {
return ENOMEM;
}
if (ret) {
return ret;
}
/* restricting to ascii chars. Need to change this when 8.8 supports */
if ((unsigned char)random_pwd[i] > 127) {
} else if (random_pwd[i] == 0) {
}
}
*randpwd = random_pwd;
return 0;
}
/*
* This function will set the password of the service object in the directory
*
*
* INPUT:
* argc - contains the number of arguments for this sub-command
* argv - array of arguments for this sub-command
*
* OUTPUT:
* void
*/
int
int argc;
char **argv;
{
/* Solaris Kerberos */
int filelen = 0;
int random_passwd = 0;
unsigned int passwd_len = 0;
int retval = 0, i = 0;
unsigned int len = 0;
/* The arguments for setsrv password should contain the service object DN
* and options to specify whether the password should be updated in file only
* or both file and directory. So the possible combination of arguments are:
* setsrvpw servicedn wherein argc is 2
* setsrvpw -fileonly servicedn wherein argc is 3
* setsrvpw -randpw servicedn wherein argc is 3
* setsrvpw -f filename servicedn wherein argc is 4
* setsrvpw -fileonly -f filename servicedn wherein argc is 5
* setsrvpw -randpw -f filename servicedn wherein argc is 5
*/
print_usage = TRUE;
goto cleanup;
}
goto cleanup;
}
/* Parse the arguments */
random_passwd = 1;
set_dir_pwd = 0;
print_usage = TRUE;
goto cleanup;
}
goto cleanup;
}
/* Verify if the file location has the proper file name
* we reject it.
*/
print_usage = TRUE;
goto cleanup;
}
} else {
print_usage = TRUE;
goto cleanup;
}
}
if (i != argc-1) {
print_usage = TRUE;
goto cleanup;
}
if (service_object == NULL) {
goto cleanup;
}
if (strlen(service_object) == 0) {
print_usage = TRUE;
goto cleanup;
}
if (service_object[0] == '-') {
print_usage = TRUE;
goto cleanup;
}
goto cleanup;
}
}
if (set_dir_pwd) {
goto cleanup;
}
}
}
if (random_passwd) {
if (!set_dir_pwd) {
print_usage = TRUE;
goto cleanup;
} else {
/* Generate random password */
goto cleanup;
}
}
} else {
/* Get the service object password from the terminal */
goto cleanup;
}
/* size of allocation=strlen of servicedn + strlen("Password for \" \"")=20 */
goto cleanup;
}
/* size of allocation=strlen of servicedn + strlen("Re-enter Password for \" \"")=30 */
goto cleanup;
}
if (retval) {
goto cleanup;
}
if (passwd_len == 0) {
goto cleanup;
}
}
/* Hex the password */
{
if (errcode != 0) {
}
goto cleanup;
}
/* Password = {CRYPT}<encrypted password>:<encrypted key> */
goto cleanup;
}
}
/* We should check if the file exists and we have permission to write into that file */
if (fd == -1) {
goto cleanup;
}
} else {
goto cleanup;
}
}
if (set_dir_pwd) {
goto cleanup;
}
}
/* TODO: file lock for the service password file */
/* set password in the file */
goto cleanup;
}
break;
}
}
}
/* If the service object dn is not present in the service password file */
goto cleanup;
}
} else {
goto cleanup;
}
} else {
/* Password entry for the service object is already present in the file */
/* Delete the existing entry and add the new entry */
/* Create a new file with the extension .tmp */
goto cleanup;
}
goto cleanup;
}
goto cleanup;
}
} else {
goto cleanup;
}
}
}
goto cleanup;
}
/* TODO: file lock for the service password file */
} else {
goto cleanup;
}
}
errcode = 0;
if (db_init_local)
if (service_object)
if (file_name)
if (passwd)
if (encrypted_passwd.value) {
}
if (pfile)
if (tmp_file)
if (print_usage)
return errcode;
}
#else /* #ifdef HAVE_EDIRECTORY */
/*
* Convert the user supplied password into hexadecimal and stash it. Only a
* little more secure than storing plain password in the file ...
*/
void
int argc;
char **argv;
{
int ret = 0;
unsigned int passwd_len = 0;
/* Solaris Kerberos */
int fd;
/*
* Format:
* stashsrvpw [-f filename] service_dn
* where
* 'service_dn' is the DN of the service object
* 'filename' is the path of the stash file
*/
print_usage = TRUE;
goto cleanup;
}
if (argc == 4) {
/* Find the stash file name */
goto cleanup;
}
goto cleanup;
}
} else {
print_usage = TRUE;
goto cleanup;
}
goto cleanup;
}
} else { /* argc == 2 */
char *section;
if (service_object == NULL) {
goto cleanup;
}
/* Pick up the stash-file name from krb5.conf */
/* Stash file path neither in krb5.conf nor on command line */
goto cleanup;
}
goto done;
}
}
/*
* Solaris Kerberos: use default if ldap_service_password_file not set
*/
goto cleanup;
}
}
}
done:
/* Get password from user */
{
/* Get the service object password from the terminal */
passwd_len = sizeof (passwd);
/* size of prompt = strlen of servicedn + strlen("Password for \" \"") */
+ sizeof ("Password for \" \"")));
/* size of prompt = strlen of servicedn + strlen("Re-enter Password for \" \"") */
+ sizeof ("Re-enter Password for \" \"")));
if (ret != 0) {
goto cleanup;
}
if (passwd_len == 0) {
goto cleanup;
}
}
/* Convert the password to hexadecimal */
{
if (ret != 0) {
goto cleanup;
}
}
/* TODO: file lock for the service passowrd file */
/* set password in the file */
#if 0 /* ************ Begin IFDEF'ed OUT ***************************** */
goto cleanup;
}
#else
/* Solaris Kerberos: safer than the above */
if (fd < 0) {
goto cleanup;
}
goto cleanup;
}
#endif
/*
* White spaces not allowed, # delimits the service dn from the
* password
*/
break;
}
}
/* If the service object dn is not present in the service password file */
goto cleanup;
}
} else {
goto cleanup;
}
} else {
/*
* Password entry for the service object is already present in the file
* Delete the existing entry and add the new entry
*/
/* Create a new file with the extension .tmp */
goto cleanup;
}
goto cleanup;
}
goto cleanup;
}
} else {
goto cleanup;
}
}
}
goto cleanup;
}
/* TODO: file lock for the service passowrd file */
if (ret != 0) {
"file"));
goto cleanup;
}
}
ret = 0;
}
if (service_object)
if (file_name)
if (tmp_file)
if (print_usage)
usage();
/* db_usage(STASH_SRV_PW); */
if (ret)
exit_status++;
}
#endif /* #ifdef HAVE_EDIRECTORY */