|
Packit |
fd8b60 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit |
fd8b60 |
/* plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c */
|
|
Packit |
fd8b60 |
/* Copyright (c) 2004-2005, Novell, Inc.
|
|
Packit |
fd8b60 |
* All rights reserved.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit |
fd8b60 |
* modification, are permitted provided that the following conditions are met:
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* * Redistributions of source code must retain the above copyright notice,
|
|
Packit |
fd8b60 |
* this list of conditions and the following disclaimer.
|
|
Packit |
fd8b60 |
* * Redistributions in binary form must reproduce the above copyright
|
|
Packit |
fd8b60 |
* notice, this list of conditions and the following disclaimer in the
|
|
Packit |
fd8b60 |
* documentation and/or other materials provided with the distribution.
|
|
Packit |
fd8b60 |
* * The copyright holder's name is not used to endorse or promote products
|
|
Packit |
fd8b60 |
* derived from this software without specific prior written permission.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
fd8b60 |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
fd8b60 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
fd8b60 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
Packit |
fd8b60 |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit |
fd8b60 |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit |
fd8b60 |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit |
fd8b60 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit |
fd8b60 |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
fd8b60 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit |
fd8b60 |
* POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Create / Delete / Modify / View / List service objects.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Service objects have rights over realm objects and principals. The following
|
|
Packit |
fd8b60 |
* functions manage the service objects.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#include <k5-int.h>
|
|
Packit |
fd8b60 |
#include <k5-hex.h>
|
|
Packit |
fd8b60 |
#include "kdb5_ldap_util.h"
|
|
Packit |
fd8b60 |
#include "kdb5_ldap_list.h"
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Get the configured LDAP service password file. The caller should free the
|
|
Packit |
fd8b60 |
* result with profile_release_string(). */
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
get_conf_service_file(profile_t profile, const char *realm, char **path_out)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
char *subsection, *path;
|
|
Packit |
fd8b60 |
long ret;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*path_out = NULL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Get the [dbmodules] subsection for realm. */
|
|
Packit |
fd8b60 |
ret = profile_get_string(profile, KDB_REALM_SECTION, realm,
|
|
Packit |
fd8b60 |
KDB_MODULE_POINTER, realm, &subsection);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Look up the password file in the [dbmodules] subsection. */
|
|
Packit |
fd8b60 |
ret = profile_get_string(profile, KDB_MODULE_SECTION, subsection,
|
|
Packit |
fd8b60 |
KRB5_CONF_LDAP_SERVICE_PASSWORD_FILE, NULL,
|
|
Packit |
fd8b60 |
&path);
|
|
Packit |
fd8b60 |
profile_release_string(subsection);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (path == NULL) {
|
|
Packit |
fd8b60 |
/* Look up the password file in [dbdefaults] as a fallback. */
|
|
Packit |
fd8b60 |
ret = profile_get_string(profile, KDB_MODULE_DEF_SECTION,
|
|
Packit |
fd8b60 |
KRB5_CONF_LDAP_SERVICE_PASSWORD_FILE, NULL,
|
|
Packit |
fd8b60 |
NULL, &path);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (path == NULL) {
|
|
Packit |
fd8b60 |
k5_setmsg(util_context, ENOENT,
|
|
Packit |
fd8b60 |
_("ldap_service_password_file not configured"));
|
|
Packit |
fd8b60 |
return ENOENT;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*path_out = path;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Convert the user supplied password into hexadecimal and stash it. Only a
|
|
Packit |
fd8b60 |
* little more secure than storing plain password in the file ...
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
void
|
|
Packit |
fd8b60 |
kdb5_ldap_stash_service_password(int argc, char **argv)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int ret = 0;
|
|
Packit |
fd8b60 |
unsigned int passwd_len = 0;
|
|
Packit |
fd8b60 |
char *me = progname;
|
|
Packit |
fd8b60 |
char *service_object = NULL;
|
|
Packit |
fd8b60 |
char *file_name = NULL, *tmp_file = NULL;
|
|
Packit |
fd8b60 |
char passwd[MAX_SERVICE_PASSWD_LEN];
|
|
Packit |
fd8b60 |
char *str = NULL, *hexpasswd = NULL;
|
|
Packit |
fd8b60 |
char line[MAX_LEN];
|
|
Packit |
fd8b60 |
FILE *pfile = NULL;
|
|
Packit |
fd8b60 |
krb5_boolean print_usage = FALSE;
|
|
Packit |
fd8b60 |
mode_t old_mode = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Format:
|
|
Packit |
fd8b60 |
* stashsrvpw [-f filename] service_dn
|
|
Packit |
fd8b60 |
* where
|
|
Packit |
fd8b60 |
* 'service_dn' is the DN of the service object
|
|
Packit |
fd8b60 |
* 'filename' is the path of the stash file
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
if (argc != 2 && argc != 4) {
|
|
Packit |
fd8b60 |
print_usage = TRUE;
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (argc == 4) {
|
|
Packit |
fd8b60 |
/* Find the stash file name */
|
|
Packit |
fd8b60 |
if (strcmp (argv[1], "-f") == 0) {
|
|
Packit |
fd8b60 |
if (((file_name = strdup (argv[2])) == NULL) ||
|
|
Packit |
fd8b60 |
((service_object = strdup (argv[3])) == NULL)) {
|
|
Packit |
fd8b60 |
com_err(me, ENOMEM,
|
|
Packit |
fd8b60 |
_("while setting service object password"));
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else if (strcmp (argv[2], "-f") == 0) {
|
|
Packit |
fd8b60 |
if (((file_name = strdup (argv[3])) == NULL) ||
|
|
Packit |
fd8b60 |
((service_object = strdup (argv[1])) == NULL)) {
|
|
Packit |
fd8b60 |
com_err(me, ENOMEM,
|
|
Packit |
fd8b60 |
_("while setting service object password"));
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
print_usage = TRUE;
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else { /* argc == 2 */
|
|
Packit |
fd8b60 |
service_object = strdup (argv[1]);
|
|
Packit |
fd8b60 |
if (service_object == NULL) {
|
|
Packit |
fd8b60 |
com_err(me, ENOMEM, _("while setting service object password"));
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = get_conf_service_file(util_context->profile,
|
|
Packit |
fd8b60 |
util_context->default_realm, &file_name);
|
|
Packit |
fd8b60 |
if (ret) {
|
|
Packit |
fd8b60 |
com_err(me, ret, _("while getting service password filename"));
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Get password from user */
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
char prompt1[256], prompt2[256];
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Get the service object password from the terminal */
|
|
Packit |
fd8b60 |
memset(passwd, 0, sizeof (passwd));
|
|
Packit |
fd8b60 |
passwd_len = sizeof (passwd);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
snprintf(prompt1, sizeof(prompt1), _("Password for \"%s\""),
|
|
Packit |
fd8b60 |
service_object);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
snprintf(prompt2, sizeof(prompt2), _("Re-enter password for \"%s\""),
|
|
Packit |
fd8b60 |
service_object);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len);
|
|
Packit |
fd8b60 |
if (ret != 0) {
|
|
Packit |
fd8b60 |
com_err(me, ret, _("while setting service object password"));
|
|
Packit |
fd8b60 |
memset(passwd, 0, sizeof (passwd));
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (passwd_len == 0) {
|
|
Packit |
fd8b60 |
printf(_("%s: Invalid password\n"), me);
|
|
Packit |
fd8b60 |
memset(passwd, 0, MAX_SERVICE_PASSWD_LEN);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Convert the password to hexadecimal */
|
|
Packit |
fd8b60 |
ret = k5_hex_encode(passwd, passwd_len, FALSE, &hexpasswd);
|
|
Packit |
fd8b60 |
zap(passwd, passwd_len);
|
|
Packit |
fd8b60 |
if (ret != 0) {
|
|
Packit |
fd8b60 |
com_err(me, ret, _("Failed to convert the password to hexadecimal"));
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* TODO: file lock for the service password file */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* set password in the file */
|
|
Packit |
fd8b60 |
old_mode = umask(0177);
|
|
rpm-build |
0599c4 |
pfile = WRITABLEFOPEN(file_name, "a+");
|
|
Packit |
fd8b60 |
if (pfile == NULL) {
|
|
Packit |
fd8b60 |
com_err(me, errno, _("Failed to open file %s: %s"), file_name,
|
|
Packit |
fd8b60 |
strerror (errno));
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
set_cloexec_file(pfile);
|
|
Packit |
fd8b60 |
rewind (pfile);
|
|
Packit |
fd8b60 |
umask(old_mode);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
while (fgets (line, MAX_LEN, pfile) != NULL) {
|
|
Packit |
fd8b60 |
if ((str = strstr (line, service_object)) != NULL) {
|
|
Packit |
fd8b60 |
/* White spaces not allowed */
|
|
Packit |
fd8b60 |
if (line [strlen (service_object)] == '#')
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
str = NULL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (str == NULL) {
|
|
Packit |
fd8b60 |
if (feof(pfile)) {
|
|
Packit |
fd8b60 |
/* If the service object dn is not present in the service password file */
|
|
Packit |
fd8b60 |
if (fprintf(pfile, "%s#{HEX}%s\n", service_object, hexpasswd) < 0) {
|
|
Packit |
fd8b60 |
com_err(me, errno,
|
|
Packit |
fd8b60 |
_("Failed to write service object password to file"));
|
|
Packit |
fd8b60 |
fclose(pfile);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
com_err(me, errno,
|
|
Packit |
fd8b60 |
_("Error reading service object password file"));
|
|
Packit |
fd8b60 |
fclose(pfile);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
fclose(pfile);
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Password entry for the service object is already present in the file
|
|
Packit |
fd8b60 |
* Delete the existing entry and add the new entry
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
FILE *newfile;
|
|
rpm-build |
0599c4 |
#ifdef USE_SELINUX
|
|
rpm-build |
0599c4 |
void *selabel;
|
|
rpm-build |
0599c4 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
mode_t omask;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Create a new file with the extension .tmp */
|
|
Packit |
fd8b60 |
if (asprintf(&tmp_file,"%s.tmp",file_name) < 0) {
|
|
Packit |
fd8b60 |
com_err(me, ENOMEM, _("while setting service object password"));
|
|
Packit |
fd8b60 |
fclose(pfile);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
omask = umask(077);
|
|
rpm-build |
0599c4 |
#ifdef USE_SELINUX
|
|
rpm-build |
0599c4 |
selabel = krb5int_push_fscreatecon_for(file_name);
|
|
rpm-build |
0599c4 |
#endif
|
|
Packit |
fd8b60 |
newfile = fopen(tmp_file, "w");
|
|
rpm-build |
0599c4 |
#ifdef USE_SELINUX
|
|
rpm-build |
0599c4 |
krb5int_pop_fscreatecon(selabel);
|
|
rpm-build |
0599c4 |
#endif
|
|
Packit |
fd8b60 |
umask (omask);
|
|
Packit |
fd8b60 |
if (newfile == NULL) {
|
|
Packit |
fd8b60 |
com_err(me, errno, _("Error creating file %s"), tmp_file);
|
|
Packit |
fd8b60 |
fclose(pfile);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
set_cloexec_file(newfile);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
fseek(pfile, 0, SEEK_SET);
|
|
Packit |
fd8b60 |
while (fgets(line, MAX_LEN, pfile) != NULL) {
|
|
Packit |
fd8b60 |
if (((str = strstr(line, service_object)) != NULL) &&
|
|
Packit |
fd8b60 |
(line[strlen(service_object)] == '#')) {
|
|
Packit |
fd8b60 |
if (fprintf(newfile, "%s#{HEX}%s\n", service_object, hexpasswd) < 0) {
|
|
Packit |
fd8b60 |
com_err(me, errno, _("Failed to write service object "
|
|
Packit |
fd8b60 |
"password to file"));
|
|
Packit |
fd8b60 |
fclose(newfile);
|
|
Packit |
fd8b60 |
unlink(tmp_file);
|
|
Packit |
fd8b60 |
fclose(pfile);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
if (fprintf (newfile, "%s", line) < 0) {
|
|
Packit |
fd8b60 |
com_err(me, errno, _("Failed to write service object "
|
|
Packit |
fd8b60 |
"password to file"));
|
|
Packit |
fd8b60 |
fclose(newfile);
|
|
Packit |
fd8b60 |
unlink(tmp_file);
|
|
Packit |
fd8b60 |
fclose(pfile);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (!feof(pfile)) {
|
|
Packit |
fd8b60 |
com_err(me, errno,
|
|
Packit |
fd8b60 |
_("Error reading service object password file"));
|
|
Packit |
fd8b60 |
fclose(newfile);
|
|
Packit |
fd8b60 |
unlink(tmp_file);
|
|
Packit |
fd8b60 |
fclose(pfile);
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* TODO: file lock for the service passowrd file */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
fclose(pfile);
|
|
Packit |
fd8b60 |
fclose(newfile);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = rename(tmp_file, file_name);
|
|
Packit |
fd8b60 |
if (ret != 0) {
|
|
Packit |
fd8b60 |
com_err(me, errno,
|
|
Packit |
fd8b60 |
_("Failed to write service object password to file"));
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
ret = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
zapfreestr(hexpasswd);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (service_object)
|
|
Packit |
fd8b60 |
free(service_object);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
profile_release_string(file_name);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (tmp_file)
|
|
Packit |
fd8b60 |
free(tmp_file);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (print_usage)
|
|
Packit |
fd8b60 |
usage();
|
|
Packit |
fd8b60 |
/* db_usage(STASH_SRV_PW); */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
exit_status++;
|
|
Packit |
fd8b60 |
}
|