|
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 |
}
|