Blame cifscreds.c

Packit Service 09cdfc
/*
Packit Service 09cdfc
 * Credentials stashing utility for Linux CIFS VFS (virtual filesystem) client
Packit Service 09cdfc
 * Copyright (C) 2010 Jeff Layton (jlayton@samba.org)
Packit Service 09cdfc
 * Copyright (C) 2010 Igor Druzhinin (jaxbrigs@gmail.com)
Packit Service 09cdfc
 *
Packit Service 09cdfc
 * This program is free software; you can redistribute it and/or modify
Packit Service 09cdfc
 * it under the terms of the GNU General Public License as published by
Packit Service 09cdfc
 * the Free Software Foundation; either version 3 of the License, or
Packit Service 09cdfc
 * (at your option) any later version.
Packit Service 09cdfc
 *
Packit Service 09cdfc
 * This program is distributed in the hope that it will be useful,
Packit Service 09cdfc
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 09cdfc
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 09cdfc
 * GNU General Public License for more details.
Packit Service 09cdfc
 *
Packit Service 09cdfc
 * You should have received a copy of the GNU General Public License
Packit Service 09cdfc
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service 09cdfc
 */
Packit Service 09cdfc
Packit Service 09cdfc
#ifdef HAVE_CONFIG_H
Packit Service 09cdfc
#include "config.h"
Packit Service 09cdfc
#endif /* HAVE_CONFIG_H */
Packit Service 09cdfc
Packit Service 09cdfc
#include <stdio.h>
Packit Service 09cdfc
#include <stdlib.h>
Packit Service 09cdfc
#include <unistd.h>
Packit Service 09cdfc
#include <string.h>
Packit Service 09cdfc
#include <ctype.h>
Packit Service 09cdfc
#include <keyutils.h>
Packit Service 09cdfc
#include <getopt.h>
Packit Service 09cdfc
#include <errno.h>
Packit Service 09cdfc
#include "cifskey.h"
Packit Service 09cdfc
#include "mount.h"
Packit Service 09cdfc
#include "resolve_host.h"
Packit Service 09cdfc
#include "util.h"
Packit Service 09cdfc
Packit Service 09cdfc
#define THIS_PROGRAM_NAME "cifscreds"
Packit Service 09cdfc
Packit Service 09cdfc
/* max length of appropriate command */
Packit Service 09cdfc
#define MAX_COMMAND_SIZE 32
Packit Service 09cdfc
Packit Service 09cdfc
struct cmdarg {
Packit Service 09cdfc
	char		*host;
Packit Service 09cdfc
	char		*user;
Packit Service 09cdfc
	char		keytype;
Packit Service 09cdfc
};
Packit Service 09cdfc
Packit Service 09cdfc
struct command {
Packit Service 09cdfc
	int (*action)(struct cmdarg *arg);
Packit Service 09cdfc
	const char	name[MAX_COMMAND_SIZE];
Packit Service 09cdfc
	const char	*format;
Packit Service 09cdfc
};
Packit Service 09cdfc
Packit Service 09cdfc
static int cifscreds_add(struct cmdarg *arg);
Packit Service 09cdfc
static int cifscreds_clear(struct cmdarg *arg);
Packit Service 09cdfc
static int cifscreds_clearall(struct cmdarg *arg);
Packit Service 09cdfc
static int cifscreds_update(struct cmdarg *arg);
Packit Service 09cdfc
Packit Service 09cdfc
static const char *thisprogram;
Packit Service 09cdfc
Packit Service 09cdfc
static struct command commands[] = {
Packit Service 09cdfc
	{ cifscreds_add,	"add",		"[-u username] [-d] <host|domain>" },
Packit Service 09cdfc
	{ cifscreds_clear,	"clear",	"[-u username] [-d] <host|domain>" },
Packit Service 09cdfc
	{ cifscreds_clearall,	"clearall",	"" },
Packit Service 09cdfc
	{ cifscreds_update,	"update",	"[-u username] [-d] <host|domain>" },
Packit Service 09cdfc
	{ NULL, "", NULL }
Packit Service 09cdfc
};
Packit Service 09cdfc
Packit Service 09cdfc
static struct option longopts[] = {
Packit Service 09cdfc
	{"username", 1, NULL, 'u'},
Packit Service 09cdfc
	{"domain", 0, NULL, 'd' },
Packit Service 09cdfc
	{NULL, 0, NULL, 0}
Packit Service 09cdfc
};
Packit Service 09cdfc
Packit Service 09cdfc
/* display usage information */
Packit Service 09cdfc
static int
Packit Service 09cdfc
usage(void)
Packit Service 09cdfc
{
Packit Service 09cdfc
	struct command *cmd;
Packit Service 09cdfc
Packit Service 09cdfc
	fprintf(stderr, "Usage:\n");
Packit Service 09cdfc
	for (cmd = commands; cmd->action; cmd++)
Packit Service 09cdfc
		fprintf(stderr, "\t%s %s %s\n", thisprogram,
Packit Service 09cdfc
			cmd->name, cmd->format);
Packit Service 09cdfc
	fprintf(stderr, "\n");
Packit Service 09cdfc
Packit Service 09cdfc
	return EXIT_FAILURE;
Packit Service 09cdfc
}
Packit Service 09cdfc
Packit Service 09cdfc
/* search all program's keys in keyring */
Packit Service 09cdfc
static key_serial_t key_search_all(void)
Packit Service 09cdfc
{
Packit Service 09cdfc
	key_serial_t key, *pk;
Packit Service 09cdfc
	void *keylist;
Packit Service 09cdfc
	char *buffer;
Packit Service 09cdfc
	int count, dpos, n, ret;
Packit Service 09cdfc
Packit Service 09cdfc
	/* read the key payload data */
Packit Service 09cdfc
	count = keyctl_read_alloc(DEST_KEYRING, &keylist);
Packit Service 09cdfc
	if (count < 0)
Packit Service 09cdfc
		return 0;
Packit Service 09cdfc
Packit Service 09cdfc
	count /= sizeof(key_serial_t);
Packit Service 09cdfc
Packit Service 09cdfc
	if (count == 0) {
Packit Service 09cdfc
		ret = 0;
Packit Service 09cdfc
		goto key_search_all_out;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	/* list the keys in the keyring */
Packit Service 09cdfc
	pk = keylist;
Packit Service 09cdfc
	do {
Packit Service 09cdfc
		key = *pk++;
Packit Service 09cdfc
Packit Service 09cdfc
		ret = keyctl_describe_alloc(key, &buffer);
Packit Service 09cdfc
		if (ret < 0)
Packit Service 09cdfc
			continue;
Packit Service 09cdfc
Packit Service 09cdfc
		n = sscanf(buffer, "%*[^;];%*d;%*d;%*x;%n", &dpos);
Packit Service 09cdfc
		if (n) {
Packit Service 09cdfc
			free(buffer);
Packit Service 09cdfc
			continue;
Packit Service 09cdfc
		}
Packit Service 09cdfc
Packit Service 09cdfc
		if (strstr(buffer + dpos, KEY_PREFIX ":") ==
Packit Service 09cdfc
			buffer + dpos
Packit Service 09cdfc
		) {
Packit Service 09cdfc
			ret = key;
Packit Service 09cdfc
			free(buffer);
Packit Service 09cdfc
			goto key_search_all_out;
Packit Service 09cdfc
		}
Packit Service 09cdfc
		free(buffer);
Packit Service 09cdfc
Packit Service 09cdfc
	} while (--count);
Packit Service 09cdfc
Packit Service 09cdfc
	ret = 0;
Packit Service 09cdfc
Packit Service 09cdfc
key_search_all_out:
Packit Service 09cdfc
	free(keylist);
Packit Service 09cdfc
	return ret;
Packit Service 09cdfc
}
Packit Service 09cdfc
Packit Service 09cdfc
/* add command handler */
Packit Service 09cdfc
static int cifscreds_add(struct cmdarg *arg)
Packit Service 09cdfc
{
Packit Service 09cdfc
	char addrstr[MAX_ADDR_LIST_LEN];
Packit Service 09cdfc
	char *currentaddress, *nextaddress;
Packit Service 09cdfc
	char *pass;
Packit Service 09cdfc
	int ret = 0;
Packit Service 09cdfc
Packit Service 09cdfc
	if (arg->host == NULL || arg->user == NULL)
Packit Service 09cdfc
		return usage();
Packit Service 09cdfc
Packit Service 09cdfc
	if (arg->keytype == 'd')
Packit Service 09cdfc
		strlcpy(addrstr, arg->host, MAX_ADDR_LIST_LEN);
Packit Service 09cdfc
	else
Packit Service 09cdfc
		ret = resolve_host(arg->host, addrstr);
Packit Service 09cdfc
Packit Service 09cdfc
	switch (ret) {
Packit Service 09cdfc
	case EX_USAGE:
Packit Service 09cdfc
		fprintf(stderr, "error: Could not resolve address "
Packit Service 09cdfc
			"for %s\n", arg->host);
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
Packit Service 09cdfc
	case EX_SYSERR:
Packit Service 09cdfc
		fprintf(stderr, "error: Problem parsing address list\n");
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	if (strpbrk(arg->user, USER_DISALLOWED_CHARS)) {
Packit Service 09cdfc
		fprintf(stderr, "error: Incorrect username\n");
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	/* search for same credentials stashed for current host */
Packit Service 09cdfc
	currentaddress = addrstr;
Packit Service 09cdfc
	nextaddress = strchr(currentaddress, ',');
Packit Service 09cdfc
	if (nextaddress)
Packit Service 09cdfc
		*nextaddress++ = '\0';
Packit Service 09cdfc
Packit Service 09cdfc
	while (currentaddress) {
Packit Service 09cdfc
		if (key_search(currentaddress, arg->keytype) > 0) {
Packit Service 09cdfc
			printf("You already have stashed credentials "
Packit Service 09cdfc
				"for %s (%s)\n", currentaddress, arg->host);
Packit Service 09cdfc
			printf("If you want to update them use:\n");
Packit Service 09cdfc
			printf("\t%s update\n", thisprogram);
Packit Service 09cdfc
Packit Service 09cdfc
			return EXIT_FAILURE;
Packit Service 09cdfc
		}
Packit Service 09cdfc
Packit Service 09cdfc
		switch(errno) {
Packit Service 09cdfc
		case ENOKEY:
Packit Service 09cdfc
			/* success */
Packit Service 09cdfc
			break;
Packit Service 09cdfc
		default:
Packit Service 09cdfc
			printf("Key search failed: %s\n", strerror(errno));
Packit Service 09cdfc
			return EXIT_FAILURE;
Packit Service 09cdfc
		}
Packit Service 09cdfc
Packit Service 09cdfc
		currentaddress = nextaddress;
Packit Service 09cdfc
		if (currentaddress) {
Packit Service 09cdfc
			*(currentaddress - 1) = ',';
Packit Service 09cdfc
			nextaddress = strchr(currentaddress, ',');
Packit Service 09cdfc
			if (nextaddress)
Packit Service 09cdfc
				*nextaddress++ = '\0';
Packit Service 09cdfc
		}
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	/*
Packit Service 09cdfc
	 * if there isn't same credentials stashed add them to keyring
Packit Service 09cdfc
	 * and set permisson mask
Packit Service 09cdfc
	 */
Packit Service 09cdfc
	pass = getpass("Password: ");
Packit Service 09cdfc
Packit Service 09cdfc
	currentaddress = addrstr;
Packit Service 09cdfc
	nextaddress = strchr(currentaddress, ',');
Packit Service 09cdfc
	if (nextaddress)
Packit Service 09cdfc
		*nextaddress++ = '\0';
Packit Service 09cdfc
Packit Service 09cdfc
	while (currentaddress) {
Packit Service 09cdfc
		key_serial_t key = key_add(currentaddress, arg->user, pass, arg->keytype);
Packit Service 09cdfc
		if (key <= 0) {
Packit Service 09cdfc
			fprintf(stderr, "error: Add credential key for %s: %s\n",
Packit Service 09cdfc
				currentaddress, strerror(errno));
Packit Service 09cdfc
		} else {
Packit Service 09cdfc
			if (keyctl(KEYCTL_SETPERM, key, CIFS_KEY_PERMS) < 0) {
Packit Service 09cdfc
				fprintf(stderr, "error: Setting permissons "
Packit Service 09cdfc
					"on key, attempt to delete...\n");
Packit Service 09cdfc
Packit Service 09cdfc
				if (keyctl(KEYCTL_UNLINK, key, DEST_KEYRING) < 0) {
Packit Service 09cdfc
					fprintf(stderr, "error: Deleting key from "
Packit Service 09cdfc
						"keyring for %s (%s)\n",
Packit Service 09cdfc
						currentaddress, arg->host);
Packit Service 09cdfc
				}
Packit Service 09cdfc
			}
Packit Service 09cdfc
		}
Packit Service 09cdfc
Packit Service 09cdfc
		currentaddress = nextaddress;
Packit Service 09cdfc
		if (currentaddress) {
Packit Service 09cdfc
			nextaddress = strchr(currentaddress, ',');
Packit Service 09cdfc
			if (nextaddress)
Packit Service 09cdfc
				*nextaddress++ = '\0';
Packit Service 09cdfc
		}
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	return EXIT_SUCCESS;
Packit Service 09cdfc
}
Packit Service 09cdfc
Packit Service 09cdfc
/* clear command handler */
Packit Service 09cdfc
static int cifscreds_clear(struct cmdarg *arg)
Packit Service 09cdfc
{
Packit Service 09cdfc
	char addrstr[MAX_ADDR_LIST_LEN];
Packit Service 09cdfc
	char *currentaddress, *nextaddress;
Packit Service 09cdfc
	int ret = 0, count = 0, errors = 0;
Packit Service 09cdfc
Packit Service 09cdfc
	if (arg->host == NULL || arg->user == NULL)
Packit Service 09cdfc
		return usage();
Packit Service 09cdfc
Packit Service 09cdfc
	if (arg->keytype == 'd')
Packit Service 09cdfc
		strlcpy(addrstr, arg->host, MAX_ADDR_LIST_LEN);
Packit Service 09cdfc
	else
Packit Service 09cdfc
		ret = resolve_host(arg->host, addrstr);
Packit Service 09cdfc
Packit Service 09cdfc
	switch (ret) {
Packit Service 09cdfc
	case EX_USAGE:
Packit Service 09cdfc
		fprintf(stderr, "error: Could not resolve address "
Packit Service 09cdfc
			"for %s\n", arg->host);
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
Packit Service 09cdfc
	case EX_SYSERR:
Packit Service 09cdfc
		fprintf(stderr, "error: Problem parsing address list\n");
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	if (strpbrk(arg->user, USER_DISALLOWED_CHARS)) {
Packit Service 09cdfc
		fprintf(stderr, "error: Incorrect username\n");
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	/*
Packit Service 09cdfc
	 * search for same credentials stashed for current host
Packit Service 09cdfc
	 * and unlink them from session keyring
Packit Service 09cdfc
	 */
Packit Service 09cdfc
	currentaddress = addrstr;
Packit Service 09cdfc
	nextaddress = strchr(currentaddress, ',');
Packit Service 09cdfc
	if (nextaddress)
Packit Service 09cdfc
		*nextaddress++ = '\0';
Packit Service 09cdfc
Packit Service 09cdfc
	while (currentaddress) {
Packit Service 09cdfc
		key_serial_t key = key_search(currentaddress, arg->keytype);
Packit Service 09cdfc
		if (key > 0) {
Packit Service 09cdfc
			if (keyctl(KEYCTL_UNLINK, key, DEST_KEYRING) < 0) {
Packit Service 09cdfc
				fprintf(stderr, "error: Removing key from "
Packit Service 09cdfc
					"keyring for %s (%s)\n",
Packit Service 09cdfc
					currentaddress, arg->host);
Packit Service 09cdfc
				errors++;
Packit Service 09cdfc
			} else {
Packit Service 09cdfc
				count++;
Packit Service 09cdfc
			}
Packit Service 09cdfc
		}
Packit Service 09cdfc
Packit Service 09cdfc
		currentaddress = nextaddress;
Packit Service 09cdfc
		if (currentaddress) {
Packit Service 09cdfc
			nextaddress = strchr(currentaddress, ',');
Packit Service 09cdfc
			if (nextaddress)
Packit Service 09cdfc
				*nextaddress++ = '\0';
Packit Service 09cdfc
		}
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	if (!count && !errors) {
Packit Service 09cdfc
		printf("You have no same stashed credentials "
Packit Service 09cdfc
			" for %s\n", arg->host);
Packit Service 09cdfc
		printf("If you want to add them use:\n");
Packit Service 09cdfc
		printf("\t%s add\n", thisprogram);
Packit Service 09cdfc
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	return EXIT_SUCCESS;
Packit Service 09cdfc
}
Packit Service 09cdfc
Packit Service 09cdfc
/* clearall command handler */
Packit Service 09cdfc
static int cifscreds_clearall(struct cmdarg *arg __attribute__ ((unused)))
Packit Service 09cdfc
{
Packit Service 09cdfc
	key_serial_t key;
Packit Service 09cdfc
	int count = 0, errors = 0;
Packit Service 09cdfc
Packit Service 09cdfc
	/*
Packit Service 09cdfc
	 * search for all program's credentials stashed in session keyring
Packit Service 09cdfc
	 * and then unlink them
Packit Service 09cdfc
	 */
Packit Service 09cdfc
	do {
Packit Service 09cdfc
		key = key_search_all();
Packit Service 09cdfc
		if (key > 0) {
Packit Service 09cdfc
			if (keyctl(KEYCTL_UNLINK, key, DEST_KEYRING) < 0) {
Packit Service 09cdfc
				fprintf(stderr, "error: Deleting key "
Packit Service 09cdfc
					"from keyring");
Packit Service 09cdfc
				errors++;
Packit Service 09cdfc
			} else {
Packit Service 09cdfc
				count++;
Packit Service 09cdfc
			}
Packit Service 09cdfc
		}
Packit Service 09cdfc
	} while (key > 0);
Packit Service 09cdfc
Packit Service 09cdfc
	if (!count && !errors) {
Packit Service 09cdfc
		printf("You have no stashed " KEY_PREFIX
Packit Service 09cdfc
			" credentials\n");
Packit Service 09cdfc
		printf("If you want to add them use:\n");
Packit Service 09cdfc
		printf("\t%s add\n", thisprogram);
Packit Service 09cdfc
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	return EXIT_SUCCESS;
Packit Service 09cdfc
}
Packit Service 09cdfc
Packit Service 09cdfc
/* update command handler */
Packit Service 09cdfc
static int cifscreds_update(struct cmdarg *arg)
Packit Service 09cdfc
{
Packit Service 09cdfc
	char addrstr[MAX_ADDR_LIST_LEN];
Packit Service 09cdfc
	char *currentaddress, *nextaddress, *pass;
Packit Service 09cdfc
	char *addrs[16];
Packit Service 09cdfc
	int ret = 0, id, count = 0;
Packit Service 09cdfc
Packit Service 09cdfc
	if (arg->host == NULL || arg->user == NULL)
Packit Service 09cdfc
		return usage();
Packit Service 09cdfc
Packit Service 09cdfc
	if (arg->keytype == 'd')
Packit Service 09cdfc
		strlcpy(addrstr, arg->host, MAX_ADDR_LIST_LEN);
Packit Service 09cdfc
	else
Packit Service 09cdfc
		ret = resolve_host(arg->host, addrstr);
Packit Service 09cdfc
Packit Service 09cdfc
	switch (ret) {
Packit Service 09cdfc
	case EX_USAGE:
Packit Service 09cdfc
		fprintf(stderr, "error: Could not resolve address "
Packit Service 09cdfc
			"for %s\n", arg->host);
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
Packit Service 09cdfc
	case EX_SYSERR:
Packit Service 09cdfc
		fprintf(stderr, "error: Problem parsing address list\n");
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	if (strpbrk(arg->user, USER_DISALLOWED_CHARS)) {
Packit Service 09cdfc
		fprintf(stderr, "error: Incorrect username\n");
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	/* search for necessary credentials stashed in session keyring */
Packit Service 09cdfc
	currentaddress = addrstr;
Packit Service 09cdfc
	nextaddress = strchr(currentaddress, ',');
Packit Service 09cdfc
	if (nextaddress)
Packit Service 09cdfc
		*nextaddress++ = '\0';
Packit Service 09cdfc
Packit Service 09cdfc
	while (currentaddress) {
Packit Service 09cdfc
		if (key_search(currentaddress, arg->keytype) > 0) {
Packit Service 09cdfc
			addrs[count] = currentaddress;
Packit Service 09cdfc
			count++;
Packit Service 09cdfc
		}
Packit Service 09cdfc
Packit Service 09cdfc
		currentaddress = nextaddress;
Packit Service 09cdfc
		if (currentaddress) {
Packit Service 09cdfc
			nextaddress = strchr(currentaddress, ',');
Packit Service 09cdfc
			if (nextaddress)
Packit Service 09cdfc
				*nextaddress++ = '\0';
Packit Service 09cdfc
		}
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	if (!count) {
Packit Service 09cdfc
		printf("You have no same stashed credentials "
Packit Service 09cdfc
			"for %s\n", arg->host);
Packit Service 09cdfc
		printf("If you want to add them use:\n");
Packit Service 09cdfc
		printf("\t%s add\n", thisprogram);
Packit Service 09cdfc
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	/* update payload of found keys */
Packit Service 09cdfc
	pass = getpass("Password: ");
Packit Service 09cdfc
Packit Service 09cdfc
	for (id = 0; id < count; id++) {
Packit Service 09cdfc
		key_serial_t key = key_add(addrs[id], arg->user, pass, arg->keytype);
Packit Service 09cdfc
		if (key <= 0)
Packit Service 09cdfc
			fprintf(stderr, "error: Update credential key "
Packit Service 09cdfc
				"for %s: %s\n", addrs[id], strerror(errno));
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	return EXIT_SUCCESS;
Packit Service 09cdfc
}
Packit Service 09cdfc
Packit Service 09cdfc
static int
Packit Service 09cdfc
check_session_keyring(void)
Packit Service 09cdfc
{
Packit Service 09cdfc
	key_serial_t	ses_key, uses_key;
Packit Service 09cdfc
Packit Service 09cdfc
	ses_key = keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0);
Packit Service 09cdfc
	if (ses_key == -1) {
Packit Service 09cdfc
		if (errno == ENOKEY)
Packit Service 09cdfc
			fprintf(stderr, "Error: you have no session keyring. "
Packit Service 09cdfc
					"Consider using pam_keyinit to "
Packit Service 09cdfc
					"install one.\n");
Packit Service 09cdfc
		else
Packit Service 09cdfc
			fprintf(stderr, "Error: unable to query session "
Packit Service 09cdfc
					"keyring: %s\n", strerror(errno));
Packit Service 09cdfc
		return (int)ses_key;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	/* A problem querying the user-session keyring isn't fatal. */
Packit Service 09cdfc
	uses_key = keyctl_get_keyring_ID(KEY_SPEC_USER_SESSION_KEYRING, 0);
Packit Service 09cdfc
	if (uses_key == -1)
Packit Service 09cdfc
		return 0;
Packit Service 09cdfc
Packit Service 09cdfc
	if (ses_key == uses_key)
Packit Service 09cdfc
		fprintf(stderr, "Warning: you have no persistent session "
Packit Service 09cdfc
				"keyring. cifscreds keys will not persist "
Packit Service 09cdfc
				"after this process exits. See "
Packit Service 09cdfc
				"pam_keyinit(8).\n");
Packit Service 09cdfc
	return 0;
Packit Service 09cdfc
}
Packit Service 09cdfc
Packit Service 09cdfc
int main(int argc, char **argv)
Packit Service 09cdfc
{
Packit Service 09cdfc
	struct command *cmd, *best;
Packit Service 09cdfc
	struct cmdarg arg;
Packit Service 09cdfc
	int n;
Packit Service 09cdfc
Packit Service 09cdfc
	memset(&arg, 0, sizeof(arg));
Packit Service 09cdfc
	arg.keytype = 'a';
Packit Service 09cdfc
Packit Service 09cdfc
	thisprogram = (char *)basename(argv[0]);
Packit Service 09cdfc
	if (thisprogram == NULL)
Packit Service 09cdfc
		thisprogram = THIS_PROGRAM_NAME;
Packit Service 09cdfc
Packit Service 09cdfc
	if (argc == 1)
Packit Service 09cdfc
		return usage();
Packit Service 09cdfc
Packit Service 09cdfc
	while((n = getopt_long(argc, argv, "du:", longopts, NULL)) != -1) {
Packit Service 09cdfc
		switch (n) {
Packit Service 09cdfc
		case 'd':
Packit Service 09cdfc
			arg.keytype = (char) n;
Packit Service 09cdfc
			break;
Packit Service 09cdfc
		case 'u':
Packit Service 09cdfc
			arg.user = optarg;
Packit Service 09cdfc
			break;
Packit Service 09cdfc
		default:
Packit Service 09cdfc
			return usage();
Packit Service 09cdfc
		}
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	if (optind >= argc)
Packit Service 09cdfc
		return usage();
Packit Service 09cdfc
Packit Service 09cdfc
	/* find the best fit command */
Packit Service 09cdfc
	best = NULL;
Packit Service 09cdfc
	n = strnlen(argv[optind], MAX_COMMAND_SIZE);
Packit Service 09cdfc
Packit Service 09cdfc
	for (cmd = commands; cmd->action; cmd++) {
Packit Service 09cdfc
		if (memcmp(cmd->name, argv[optind], n) != 0)
Packit Service 09cdfc
			continue;
Packit Service 09cdfc
Packit Service 09cdfc
		if (cmd->name[n] == 0) {
Packit Service 09cdfc
			/* exact match */
Packit Service 09cdfc
			best = cmd;
Packit Service 09cdfc
			break;
Packit Service 09cdfc
		}
Packit Service 09cdfc
Packit Service 09cdfc
		/* partial match */
Packit Service 09cdfc
		if (best) {
Packit Service 09cdfc
			fprintf(stderr, "Ambiguous command\n");
Packit Service 09cdfc
			return EXIT_FAILURE;
Packit Service 09cdfc
		}
Packit Service 09cdfc
Packit Service 09cdfc
		best = cmd;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	if (!best) {
Packit Service 09cdfc
		fprintf(stderr, "Unknown command\n");
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	/* second argument should be host or domain */
Packit Service 09cdfc
	if (argc >= 3)
Packit Service 09cdfc
		arg.host = argv[optind + 1];
Packit Service 09cdfc
Packit Service 09cdfc
	if (arg.host && arg.keytype == 'd' &&
Packit Service 09cdfc
	    strpbrk(arg.host, DOMAIN_DISALLOWED_CHARS)) {
Packit Service 09cdfc
		fprintf(stderr, "error: Domain name contains invalid characters\n");
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
	}
Packit Service 09cdfc
Packit Service 09cdfc
	if (arg.user == NULL)
Packit Service 09cdfc
		arg.user = getusername(getuid());
Packit Service 09cdfc
Packit Service 09cdfc
	if (check_session_keyring())
Packit Service 09cdfc
		return EXIT_FAILURE;
Packit Service 09cdfc
Packit Service 09cdfc
	return best->action(&arg;;
Packit Service 09cdfc
}