Example #1
0
static void list_keys(const char *ring_name, key_serial_t ring_id)
{
	key_serial_t *key;
	void *keylist;
	int count;

	count = keyctl_read_alloc(ring_id, &keylist);
	if (count < 0) {
		xlog_err("Failed to read keyring %s: %m", ring_name);
		return;
	}
	count /= (int)sizeof(*key);

	switch (count) {
	case 0:
		printf("No %s keys found.\n", ring_name);
		break;
	case 1:
		printf("1 %s key found:\n", ring_name);
		break;
	default:
		printf("%u %s keys found:\n", count, ring_name);
	}

	for (key = keylist; count--; key++)
		list_key(*key);

	free(keylist);
}
Example #2
0
char * _RequestPass(/*@unused@*/ const char * prompt)
{
/*@only@*/ /*@relnull@*/
    static char * password = NULL;
#if defined(HAVE_KEYUTILS_H)
    const char * foo = "user rpm:yyyy spoon";
    ARGV_t av = NULL;
    int xx = argvSplit(&av, foo, NULL);
    key_serial_t dest = 0;
    key_serial_t key = 0;

    if (password != NULL) {
	free(password);
	password = NULL;
    }
assert(av != NULL);
assert(av[0] != NULL);
assert(av[1] != NULL);
assert(av[2] != NULL);
    key = request_key(av[0], av[1], av[2], dest);
    av = argvFree(av);

/*@-nullstate@*/	/* XXX *password may be null. */
    xx = keyctl_read_alloc(key, (void **)&password);
/*@=nullstate@*/
    if (password == NULL)
	password = (char *) "";
#endif	/* HAVE_KEYUTILS_H */

/*@-statictrans@*/
    return password;
/*@=statictrans@*/
}
Example #3
0
static int
lookup_reauthorize_secret (const char *user,
                           char **secret)
{
  char *buffer = NULL;
  char *name = NULL;
  key_serial_t key;
  int ret;

  if (asprintf (&name, "reauthorize/secret/%s", user) < 0)
    {
      message ("failed to allocate secret name");
      ret = -ENOMEM;
      goto out;
    }

  key = keyctl_search (KEY_SPEC_SESSION_KEYRING, "user", name, 0);
  if (key < 0)
    {
      /* missing key is not an error */
      if (errno == ENOKEY)
        {
          ret = 0;
          *secret = NULL;
          goto out;
        }

      ret = -errno;
      message ("failed to lookup reauthorize secret key: %s: %m", name);
      goto out;
    }

  if (keyctl_describe_alloc (key, &buffer) < 0)
    {
      ret = -errno;
      message ("couldn't describe reauthorize secret key: %s: %m", name);
      goto out;
    }
  if (strncmp (buffer, "user;0;0;001f0000;", 18) != 0)
    {
      ret = -EPERM;
      message ("kernel reauthorize secret key has invalid permissions: %s: %s", name, buffer);
      goto out;
    }

  /* null-terminates */
  if (keyctl_read_alloc (key, (void **)secret) < 0)
    {
      ret = -errno;
      message ("couldn't read kernel reauthorize secret key: %s: %m", name);
      goto out;
    }

  ret = 0;

out:
  free (buffer);
  free (name);
  return ret;
}
Example #4
0
const char * rpmkuPassPhrase(const char * passPhrase)
{
    const char * pw;

#if defined(HAVE_KEYUTILS_H)
    if (passPhrase && !strcmp(passPhrase, "@u user rpm:passwd")) {
	key_serial_t keyring = (key_serial_t) _kuKeyring;
	long key;
	int xx;

/*@-moduncon@*/
	key = keyctl_search(keyring, "user", "rpm:passwd", 0);
	pw = NULL;
	xx = keyctl_read_alloc(key, (void **)&pw);
/*@=moduncon@*/
	if (xx < 0)
	    pw = NULL;
    } else
#endif	/* HAVE_KEYUTILS_H */
	pw = xstrdup(passPhrase);
    return pw;
}
Example #5
0
int main(int argc, char *argv[])
{
	int ktlen, qtlen, ret;
	char *keyend, *p;
	char *callout_info = NULL;
	char *buf = NULL, *name;

	openlog(prog, 0, LOG_DAEMON);

	while ((ret = getopt_long(argc, argv, "vD", long_options, NULL)) != -1) {
		switch (ret) {
		case 'D':
			debug_mode = 1;
			continue;
		case 'V':
			printf("version: %s from %s (%s)\n",
			       DNS_PARSE_VERSION,
			       keyutils_version_string,
			       keyutils_build_string);
			exit(0);
		case 'v':
			verbose++;
			continue;
		default:
			if (!isatty(2))
				syslog(LOG_ERR, "unknown option: %c", ret);
			usage();
		}
	}

	argc -= optind;
	argv += optind;

	if (!debug_mode) {
		if (argc != 1)
			usage();

		/* get the key ID */
		errno = 0;
		key = strtol(*argv, NULL, 10);
		if (errno != 0)
			error("Invalid key ID format: %m");

		/* get the key description (of the form "x;x;x;x;<query_type>:<name>") */
		if (!buf) {
			ret = keyctl_describe_alloc(key, &buf);
			if (ret == -1)
				error("keyctl_describe_alloc failed: %m");
		}

		/* get the callout_info (which can supply options) */
		if (!callout_info) {
			ret = keyctl_read_alloc(KEY_SPEC_REQKEY_AUTH_KEY,
						(void **)&callout_info);
			if (ret == -1)
				error("Invalid key callout_info read: %m");
		}
	} else {
		if (argc != 2)
			usage();

		ret = asprintf(&buf, "%s;-1;-1;0;%s", key_type, argv[0]);
		if (ret < 0)
			error("Error %m");
		callout_info = argv[1];
	}

	ret = 1;
	info("Key description: '%s'", buf);
	info("Callout info: '%s'", callout_info);

	p = strchr(buf, ';');
	if (!p)
		error("Badly formatted key description '%s'", buf);
	ktlen = p - buf;

	/* make sure it's the type we are expecting */
	if (ktlen != sizeof(key_type) - 1 ||
	    memcmp(buf, key_type, ktlen) != 0)
		error("Key type is not supported: '%*.*s'", ktlen, ktlen, buf);

	keyend = buf + ktlen + 1;

	/* the actual key description follows the last semicolon */
	keyend = rindex(keyend, ';');
	if (!keyend)
		error("Invalid key description: %s", buf);
	keyend++;

	name = index(keyend, ':');
	if (!name)
		dns_query_a_or_aaaa(key, keyend, callout_info);

	qtlen = name - keyend;
	name++;

	if ((qtlen == sizeof(a_query_type) - 1 &&
	     memcmp(keyend, a_query_type, sizeof(a_query_type) - 1) == 0) ||
	    (qtlen == sizeof(aaaa_query_type) - 1 &&
	     memcmp(keyend, aaaa_query_type, sizeof(aaaa_query_type) - 1) == 0)
	    ) {
		info("Do DNS query of A/AAAA type for:'%s' mask:'%s'",
		     name, callout_info);
		dns_query_a_or_aaaa(key, name, callout_info);
	}

	if (qtlen == sizeof(afsdb_query_type) - 1 &&
	    memcmp(keyend, afsdb_query_type, sizeof(afsdb_query_type) - 1) == 0
	    ) {
		info("Do DNS query of AFSDB type for:'%s' mask:'%s'",
		     name, callout_info);
		dns_query_afsdb(key, name, callout_info);
	}

	error("Query type: \"%*.*s\" is not supported", qtlen, qtlen, keyend);
}
Example #6
0
int parse_packet(struct ecryptfs_ctx *ctx,
		 struct ecryptfs_message *emsg,
		 struct ecryptfs_message **reply)
{
	struct ecryptfs_auth_tok *auth_tok = NULL;
	size_t i = 0;
	size_t data_size;
	size_t key_size;
	size_t length_size;
	size_t key_out_size;
	unsigned char *signature = NULL;
	unsigned char packet_type;
	char *key = NULL;
	char *key_out = NULL;
	key_serial_t key_sub;
	int rc;

	packet_type = emsg->data[i++];
	if ((rc = ecryptfs_parse_packet_length(&emsg->data[i], &data_size,
					       &length_size))) {
		syslog(LOG_ERR, "Invalid packet format\n");
		goto write_failure;
	}
	i += length_size;
	signature = malloc(data_size + 1);
	if (!signature) {
		rc = -errno;
		syslog(LOG_ERR, "Failed to allocate memory: %m\n");
		goto write_failure;
	}
	memcpy(signature, &emsg->data[i], data_size);
	signature[data_size] = '\0';
	i += data_size;
	rc = ecryptfs_parse_packet_length(&emsg->data[i], &key_size,
					  &length_size);
	if (rc) {
		syslog(LOG_ERR, "Invalid packet format\n");
		goto write_failure;
	}
	i += length_size;
	if ((key = malloc(key_size)) == NULL) {
		rc = -ENOMEM;
		syslog(LOG_ERR, "Failed to allocate memory\n");
		goto write_failure;
	}
	memcpy(key, &emsg->data[i], key_size);
	i += key_size;
	key_sub = request_key("user", (char *)signature, NULL,
			      KEY_SPEC_USER_KEYRING);
	if (key_sub < 0) {
		syslog(LOG_ERR, "Could not find key with signature: "
		       "[%s]\n", signature);
		rc = -EINVAL;
		goto write_failure;
	}
	rc = keyctl_read_alloc(key_sub, (void **)(&auth_tok));
	switch (packet_type) {
	case ECRYPTFS_TAG_64_PACKET:
		if ((rc = key_mod_decrypt(&key_out, &key_out_size, ctx,
					  auth_tok, key, key_size))) {
			syslog(LOG_ERR, "Failed to decrypt key; rc = [%d]\n",
			       rc);
			rc = write_failure_packet(ECRYPTFS_TAG_65_PACKET,
						  reply);
			goto write_failure;
		}
		if ((rc = write_tag_65_packet((unsigned char *)key_out,
					      key_out_size, reply))) {
			syslog(LOG_ERR, "Failed to write decrypted "
			       "key via tag 65 packet\n");
			goto write_failure;
		}
		break;
	case ECRYPTFS_TAG_66_PACKET:
		rc = key_mod_encrypt(&key_out, &key_out_size, ctx, auth_tok,
				     key, key_size);
		if (rc) {
			syslog(LOG_ERR, "Failed to encrypt public "
			       "key\n");
			goto write_failure;
		}
		rc = write_tag_67_packet(key_out, key_out_size, reply);
		if (rc) {
			syslog(LOG_ERR, "Failed to write encrypted "
			       "key to tag 67 packet\n");
			goto write_failure;
		}
		break;
	default:
		syslog(LOG_ERR, "Unrecognized packet type: [%d]\n",
		       packet_type);
		rc = -EINVAL;
		break;
	}
	free(key);
	free(signature);
	free(key_out);
	memset(auth_tok, 0, (sizeof(struct ecryptfs_auth_tok)
			     + auth_tok->token.private_key.data_len));
	free(auth_tok);
	return rc;
write_failure:
	if(packet_type == ECRYPTFS_TAG_66_PACKET)
		rc = write_failure_packet(ECRYPTFS_TAG_67_PACKET, reply);
	else
		rc = write_failure_packet(ECRYPTFS_TAG_65_PACKET, reply);
	free(key);
	free(signature);
	free(key_out);
	if (auth_tok) {
		memset(auth_tok, 0, (sizeof(struct ecryptfs_auth_tok)
				     + auth_tok->token.private_key.data_len));
		free(auth_tok);
	}
	return rc;
}
/*
 * execute a program to deal with a key
 */
static void execute_program(char *op,
			    key_serial_t key,
			    char *ktype,
			    char *kdesc,
			    char *callout_info,
			    char *cmdline)
{
	char *argv[256];
	char *prog, *p, *q;
	int argc, pipeit;

	debug("execute_program('%s','%s')\n", callout_info, cmdline);

	/* if the commandline begins with a bar, then we pipe the callout data into it and read
	 * back the payload data
	 */
	pipeit = 0;

	if (cmdline[0] == '|') {
		pipeit = 1;
		cmdline++;
	}

	/* extract the path to the program to run */
	prog = p = cmdline;
	while (*p && !isspace(*p)) p++;
//	if (!*p)
//		error("/etc/request-key.conf:%d: No command path\n", confline);
//	*p++ = 0;
	if (*p)
		*p++ = 0;

	argv[0] = strrchr(prog, '/') + 1;

	/* extract the arguments */
	for (argc = 1; p; argc++) {
		while (isspace(*p)) p++;
		if (!*p)
			break;

		if (argc >= 254)
			error("/etc/request-key.conf:%d: Too many arguments\n", confline);
		argv[argc] = q = p;

		while (*p && !isspace(*p)) p++;

		if (*p)
			*p++ = 0;
		else
			p = NULL;

		debug("argv[%d]: '%s'\n", argc, argv[argc]);

		if (*q != '%')
			continue;

		/* it's a macro */
		q++;
		if (!*q)
			error("/etc/request-key.conf:%d: Missing macro name\n", confline);

		if (*q == '%') {
			/* it's actually an anti-macro escape "%%..." -> "%..." */
			argv[argc]++;
			continue;
		}

		/* single character macros */
		if (!q[1]) {
			switch (*q) {
			case 'o': argv[argc] = op;			continue;
			case 'k': argv[argc] = xkey;			continue;
			case 't': argv[argc] = ktype;			continue;
			case 'd': argv[argc] = kdesc;			continue;
			case 'c': argv[argc] = callout_info;		continue;
			case 'u': argv[argc] = xuid;			continue;
			case 'g': argv[argc] = xgid;			continue;
			case 'T': argv[argc] = xthread_keyring;		continue;
			case 'P': argv[argc] = xprocess_keyring;	continue;
			case 'S': argv[argc] = xsession_keyring;	continue;
			default:
				error("/etc/request-key.conf:%d: Unsupported macro\n", confline);
			}
		}

		/* keysub macro */
		if (*q == '{') {
			key_serial_t keysub;
			void *tmp;
			char *ksdesc, *end, *subdata;
			int ret, loop;

			/* extract type and description */
			q++;
			ksdesc = strchr(q, ':');
			if (!ksdesc)
				error("/etc/request-key.conf:%d: Keysub macro lacks ':'\n",
				      confline);
			*ksdesc++ = 0;
			end = strchr(ksdesc, '}');
			if (!end)
				error("/etc/request-key.conf:%d: Unterminated keysub macro\n",
				      confline);

			*end++ = 0;
			if (*end)
				error("/etc/request-key.conf:%d:"
				      " Keysub macro has trailing rubbish\n",
				      confline);

			debug("Keysub: %s key \"%s\"\n", q, ksdesc);

			if (!q[0])
				error("/etc/request-key.conf:%d: Keysub type empty\n", confline);

			if (!ksdesc[0])
				error("/etc/request-key.conf:%d: Keysub description empty\n",
				      confline);

			/* look up the key in the requestor's keyrings, but fail immediately if the
			 * key is not found rather than invoking /sbin/request-key again
			 */
			keysub = request_key(q, ksdesc, NULL, 0);
			if (keysub < 0)
				error("/etc/request-key.conf:%d:"
				      " Keysub key not found: %m\n",
				      confline);

			ret = keyctl_read_alloc(keysub, &tmp);
			if (ret < 0)
				error("/etc/request-key.conf:%d:"
				      " Can't read keysub %d data: %m\n",
				      confline, keysub);
			subdata = tmp;

			for (loop = 0; loop < ret; loop++)
				if (!isprint(subdata[loop]))
					error("/etc/request-key.conf:%d:"
					      " keysub %d data not printable ('%02hhx')\n",
					      confline, keysub, subdata[loop]);

			argv[argc] = subdata;
			continue;
		}
	}

	if (argc == 0)
		error("/etc/request-key.conf:%d: No arguments\n", confline);

	argv[argc] = NULL;

	if (xdebug) {
		char **ap;

		debug("%s %s\n", pipeit ? "PipeThru" : "Run", prog);
		for (ap = argv; *ap; ap++)
			debug("- argv[%zd] = \"%s\"\n", ap - argv, *ap);
	}

	/* become the same UID/GID as the key requesting process */
	//setgid(atoi(xuid));
	//setuid(atoi(xgid));

	/* if the last argument is a single bar, we spawn off the program dangling on the end of
	 * three pipes and read the key material from the program, otherwise we just exec
	 */
	if (pipeit)
		pipe_to_program(op, key, ktype, kdesc, callout_info, prog, argv);

	/* attempt to execute the command */
	execv(prog, argv);

	error("/etc/request-key.conf:%d: Failed to execute '%s': %m\n", confline, prog);

} /* end execute_program() */
int main(int argc, char *argv[])
{
	key_serial_t key;
	char *ktype, *kdesc, *buf, *callout_info;
	int ret, ntype, dpos, n, fd;

	signal(SIGSEGV, oops);
	signal(SIGBUS, oops);
	signal(SIGPIPE, SIG_IGN);

	for (;;) {
		if (argc > 1 && strcmp(argv[1], "-d") == 0) {
			xdebug++;
			argv++;
			argc--;
		}
		else if (argc > 1 && strcmp(argv[1], "-n") == 0) {
			xnolog = 1;
			argv++;
			argc--;
		}
		else
			break;
	}

	if (argc != 8 && argc != 9)
		error("Unexpected argument count: %d\n", argc);

	fd = open("/dev/null", O_RDWR);
	if (fd < 0)
		error("open");
	if (fd > 2) {
		close(fd);
	}
	else if (fd < 2) {
		ret = dup(fd);
		if (ret < 0)
			error("dup failed: %m\n");

		if (ret < 2 && dup(fd) < 0)
			error("dup failed: %m\n");
	}

	xkey = argv[2];
	xuid = argv[3];
	xgid = argv[4];
	xthread_keyring = argv[5];
	xprocess_keyring = argv[6];
	xsession_keyring = argv[7];

	key = atoi(xkey);

	/* assume authority over the key
	 * - older kernel doesn't support this function
	 */
	ret = keyctl_assume_authority(key);
	if (ret < 0 && !(argc == 9 || errno == EOPNOTSUPP))
		error("Failed to assume authority over key %d (%m)\n", key);

	/* ask the kernel to describe the key to us */
	if (xdebug < 2) {
		ret = keyctl_describe_alloc(key, &buf);
		if (ret < 0)
			goto inaccessible;
	}
	else {
		buf = strdup("user;0;0;1f0000;debug:1234");
	}

	/* extract the type and description from the key */
	debug("Key descriptor: \"%s\"\n", buf);
	ntype = -1;
	dpos = -1;

	n = sscanf(buf, "%*[^;]%n;%*d;%*d;%x;%n", &ntype, &n, &dpos);
	if (n != 1)
		error("Failed to parse key description\n");

	ktype = buf;
	ktype[ntype] = 0;
	kdesc = buf + dpos;

	debug("Key type: %s\n", ktype);
	debug("Key desc: %s\n", kdesc);

	/* get hold of the callout info */
	callout_info = argv[8];

	if (!callout_info) {
		void *tmp;

		if (keyctl_read_alloc(KEY_SPEC_REQKEY_AUTH_KEY, &tmp) < 0)
			error("Failed to retrieve callout info (%m)\n");

		callout_info = tmp;
	}

	debug("CALLOUT: '%s'\n", callout_info);

	/* determine the action to perform */
	lookup_action(argv[1],		/* op */
		      key,		/* ID of key under construction */
		      ktype,		/* key type */
		      kdesc,		/* key description */
		      callout_info	/* call out information */
		      );

inaccessible:
	error("Key %d is inaccessible (%m)\n", key);

} /* end main() */
Example #9
0
int main(int argc, char **argv) {
	unsigned int version = 0, help = 0;
	char challenge_old[CHALLENGELEN + 1],
		challenge_new[CHALLENGELEN + 1],
		response_old[RESPONSELEN],
		response_new[RESPONSELEN],
		passphrase_old[PASSPHRASELEN + 1],
		passphrase_new[PASSPHRASELEN + 1];
		const char * tmp;
	char challengefilename[sizeof(CHALLENGEDIR) + 11 /* "/challenge-" */ + 10 /* unsigned int in char */ + 1],
		challengefiletmpname[sizeof(CHALLENGEDIR) + 11 /* "/challenge-" */ + 10 /* unsigned int in char */ + 7 /* -XXXXXX */ + 1];
	int challengefile = 0, challengefiletmp = 0;
	struct timeval tv;
	int i;
	size_t len;
	int8_t rc = EXIT_FAILURE;
	/* cryptsetup */
	const char * device_name;
	int8_t luks_slot = -1;
	struct crypt_device *cryptdevice;
	crypt_status_info cryptstatus;
	crypt_keyslot_info cryptkeyslot;
	char * passphrase = NULL;
	/* keyutils */
	key_serial_t key;
	void * payload = NULL;
	char * second_factor = NULL, * new_2nd_factor = NULL, * new_2nd_factor_verify = NULL;
	/* yubikey */
	YK_KEY * yk;
	uint8_t yk_slot = SLOT_CHAL_HMAC2;
	unsigned int serial = 0;
	/* iniparser */
	dictionary * ini;
	char section_ykslot[10 /* unsigned int in char */ + 1 + sizeof(CONFYKSLOT) + 1];
	char section_luksslot[10 + 1 + sizeof(CONFLUKSSLOT) + 1];

	/* get command line options */
	while ((i = getopt_long(argc, argv, optstring, options_long, NULL)) != -1)
		switch (i) {
			case 'h':
				help++;
				break;
			case 'n':
			case 'N':
				if (new_2nd_factor != NULL) {
					fprintf(stderr, "We already have a new second factor. Did you specify it twice?\n");
					goto out10;
				}

				if (optarg == NULL) { /* N */
					if ((new_2nd_factor = ask_secret("new second factor")) == NULL)
						goto out10;

					if ((new_2nd_factor_verify = ask_secret("new second factor for verification")) == NULL)
						goto out10;

					if (strcmp(new_2nd_factor, new_2nd_factor_verify) != 0) {
						fprintf(stderr, "Verification failed, given strings do not match.\n");
						goto out10;
					}
				} else { /* n */
					new_2nd_factor = strdup(optarg);
					memset(optarg, '*', strlen(optarg));
				}

				break;
			case 's':
			case 'S':
				if (second_factor != NULL) {
					fprintf(stderr, "We already have a second factor. Did you specify it twice?\n");
					goto out10;
				}

				if (optarg == NULL) { /* S */
					second_factor = ask_secret("current second factor");
				} else { /* s */
					second_factor = strdup(optarg);
					memset(optarg, '*', strlen(optarg));
				}

				break;
			case 'V':
				version++;
				break;
		}

	if (version > 0)
		printf("%s: %s v%s (compiled: " __DATE__ ", " __TIME__ ")\n", argv[0], PROGNAME, VERSION);

	if (help > 0)
		fprintf(stderr, "usage: %s [-h|--help] [-n|--new-2nd-factor <new-2nd-factor>] [-N|--ask-new-2nd-factor]\n"
				"        [-s|--2nd-factor <2nd-factor>] [-S|--ask-2nd-factor] [-V|--version]\n", argv[0]);

	if (version > 0 || help > 0)
		return EXIT_SUCCESS;


	/* initialize random seed */
	gettimeofday(&tv, NULL);
	srand(tv.tv_usec * tv.tv_sec);

	/* initialize static buffers */
	memset(challenge_old, 0, CHALLENGELEN + 1);
	memset(challenge_new, 0, CHALLENGELEN + 1);
	memset(response_old, 0, RESPONSELEN);
	memset(response_new, 0, RESPONSELEN);
	memset(passphrase_old, 0, PASSPHRASELEN + 1);
	memset(passphrase_new, 0, PASSPHRASELEN + 1);

	if ((ini = iniparser_load(CONFIGFILE)) == NULL) {
		fprintf(stderr, "Could not parse configuration file.\n");
		goto out10;
	}

	if ((device_name = iniparser_getstring(ini, "general:" CONFDEVNAME, NULL)) == NULL) {
		/* read from crypttab? */
		/* get device from currently open devices? */
		fprintf(stderr, "Could not read LUKS device from configuration file.\n");
		goto out20;
	}

	/* init and open first Yubikey */
	if (yk_init() == 0) {
		perror("yk_init() failed");
		goto out20;
	}

	if ((yk = yk_open_first_key()) == NULL) {
		fprintf(stderr, "No Yubikey available.\n");
		goto out30;
	}

	/* read the serial number from key */
	if (yk_get_serial(yk, 0, 0, &serial) == 0) {
		perror("yk_get_serial() failed");
		goto out40;
	}

	/* get the yk slot */
	sprintf(section_ykslot, "%d:" CONFYKSLOT, serial);
	yk_slot = iniparser_getint(ini, "general:" CONFYKSLOT, yk_slot);
	yk_slot = iniparser_getint(ini, section_ykslot, yk_slot);
	switch (yk_slot) {
		case 1:
		case SLOT_CHAL_HMAC1:
			yk_slot = SLOT_CHAL_HMAC1;
			break;
		case 2:
		case SLOT_CHAL_HMAC2:
		default:
			yk_slot = SLOT_CHAL_HMAC2;
			break;
	}

	/* get the luks slot */
	sprintf(section_luksslot, "%d:" CONFLUKSSLOT, serial);
	luks_slot = iniparser_getint(ini, section_luksslot, luks_slot);
	if (luks_slot < 0) {
		fprintf(stderr, "Please set LUKS key slot for Yubikey with serial %d!\n"
				"Add something like this to " CONFIGFILE ":\n\n"
				"[%d]\nluks slot = 1\n", serial, serial);
		goto out40;
	}

	if (second_factor == NULL) {
		/* get second factor from key store */
		if ((key = request_key("user", "ykfde-2f", NULL, 0)) < 0)
			fprintf(stderr, "Failed requesting key. That's ok if you do not use\n"
					"second factor. Give it manually if required.\n");

		if (key > -1) {
			/* if we have a key id we have a key - so this should succeed */
			if (keyctl_read_alloc(key, &payload) < 0) {
				perror("Failed reading payload from key");
				goto out40;
			}
			second_factor = payload;
		} else
			second_factor = strdup("");
	}

	/* warn when second factor is not enabled in config */
	if ((*second_factor != 0 || new_2nd_factor != NULL) &&
			iniparser_getboolean(ini, "general:" CONF2NDFACTOR, 0) == 0)
		fprintf(stderr, "Warning: Processing second factor, but not enabled in config!\n");

	/* get random number and limit to printable ASCII character (32 to 126) */
	for(i = 0; i < CHALLENGELEN; i++)
		challenge_new[i] = (rand() % (126 - 32)) + 32;

	/* these are the filenames for challenge
	 * we need this for reading and writing */
	sprintf(challengefilename, CHALLENGEDIR "/challenge-%d", serial);
	sprintf(challengefiletmpname, CHALLENGEDIR "/challenge-%d-XXXXXX", serial);

	/* write new challenge to file */
	if ((challengefiletmp = mkstemp(challengefiletmpname)) < 0) {
		fprintf(stderr, "Could not open file %s for writing.\n", challengefiletmpname);
		goto out40;
	}
	if (write(challengefiletmp, challenge_new, CHALLENGELEN) < 0) {
		fprintf(stderr, "Failed to write challenge to file.\n");
		goto out50;
	}
	challengefiletmp = close(challengefiletmp);

	/* now that the new challenge has been written to file...
	 * add second factor to new challenge */
	tmp = new_2nd_factor ? new_2nd_factor : second_factor;
	len = strlen(tmp);
	memcpy(challenge_new, tmp, len < MAX2FLEN ? len : MAX2FLEN);

	/* do challenge/response and encode to hex */
	if (yk_challenge_response(yk, yk_slot, true,
			CHALLENGELEN, (unsigned char *) challenge_new,
			RESPONSELEN, (unsigned char *) response_new) == 0) {
		perror("yk_challenge_response() failed");
		goto out50;
	}
	yubikey_hex_encode((char *) passphrase_new, (char *) response_new, SHA1_DIGEST_SIZE);

	/* get status of crypt device
	 * We expect this to be active (or busy). It is the actual root device, no? */
	cryptstatus = crypt_status(cryptdevice, device_name);
	if (cryptstatus != CRYPT_ACTIVE && cryptstatus != CRYPT_BUSY) {
                fprintf(stderr, "Device %s is invalid or inactive.\n", device_name);
		goto out50;
	}

	/* initialize crypt device */
	if (crypt_init_by_name(&cryptdevice, device_name) < 0) {
		fprintf(stderr, "Device %s failed to initialize.\n", device_name);
		goto out60;
	}

	cryptkeyslot = crypt_keyslot_status(cryptdevice, luks_slot);

	if (cryptkeyslot == CRYPT_SLOT_INVALID) {
		fprintf(stderr, "Key slot %d is invalid.\n", luks_slot);
		goto out60;
	} else if (cryptkeyslot == CRYPT_SLOT_ACTIVE || cryptkeyslot == CRYPT_SLOT_ACTIVE_LAST) {
		/* read challenge from file */
		if ((challengefile = open(challengefilename, O_RDONLY)) < 0) {
			perror("Failed opening challenge file for reading");
			goto out60;
		}

		if (read(challengefile, challenge_old, CHALLENGELEN) < 0) {
			perror("Failed reading challenge from file");
			goto out60;
		}

		challengefile = close(challengefile);
		/* finished reading challenge */

		/* copy the second factor */
		len = strlen(second_factor);
		memcpy(challenge_old, second_factor, len < MAX2FLEN ? len : MAX2FLEN);

		/* do challenge/response and encode to hex */
		if (yk_challenge_response(yk, yk_slot, true,
				CHALLENGELEN, (unsigned char *) challenge_old,
				RESPONSELEN, (unsigned char *) response_old) == 0) {
			perror("yk_challenge_response() failed");
			goto out60;
		}
		yubikey_hex_encode((char *) passphrase_old, (char *) response_old, SHA1_DIGEST_SIZE);

		if (crypt_keyslot_change_by_passphrase(cryptdevice, luks_slot, luks_slot,
				passphrase_old, PASSPHRASELEN,
				passphrase_new, PASSPHRASELEN) < 0) {
			fprintf(stderr, "Could not update passphrase for key slot %d.\n", luks_slot);
			goto out60;
		}

		if (unlink(challengefilename) < 0) {
			fprintf(stderr, "Failed to delete old challenge file.\n");
			goto out60;
		}
	} else { /* ck == CRYPT_SLOT_INACTIVE */
		if ((passphrase = ask_secret("existing LUKS passphrase")) == NULL)
			goto out60;

		if (crypt_keyslot_add_by_passphrase(cryptdevice, luks_slot,
				passphrase, strlen(passphrase),
				passphrase_new, PASSPHRASELEN) < 0) {
			fprintf(stderr, "Could not add passphrase for key slot %d.\n", luks_slot);
			goto out60;
		}
	}

	if (rename(challengefiletmpname, challengefilename) < 0) {
		fprintf(stderr, "Failed to rename new challenge file.\n");
		goto out60;
	}

	rc = EXIT_SUCCESS;

out60:
	/* free crypt context */
	crypt_free(cryptdevice);

out50:
	/* close the challenge file */
	if (challengefile)
		close(challengefile);
	if (challengefiletmp)
		close(challengefiletmp);
	if (access(challengefiletmpname, F_OK) == 0)
		unlink(challengefiletmpname);

out40:
	/* close Yubikey */
	if (yk_close_key(yk) == 0)
		perror("yk_close_key() failed");

out30:
	/* release Yubikey */
	if (yk_release() == 0)
		perror("yk_release() failed");

out20:
	/* free iniparser dictionary */
	iniparser_freedict(ini);

out10:
	/* wipe response (cleartext password!) from memory */
	/* This is statically allocated and always save to wipe! */
	memset(challenge_old, 0, CHALLENGELEN + 1);
	memset(challenge_new, 0, CHALLENGELEN + 1);
	memset(response_old, 0, RESPONSELEN);
	memset(response_new, 0, RESPONSELEN);
	memset(passphrase_old, 0, PASSPHRASELEN + 1);
	memset(passphrase_new, 0, PASSPHRASELEN + 1);

	free(passphrase);
	free(new_2nd_factor_verify);
	free(new_2nd_factor);
	free(second_factor);

	return rc;
}
Example #10
0
int main( int argc, const char* argv[] )
{
  // user id and gid
  uid_t uid, gid;
  int ret;
  int rez1,rez2;
  void *buffer;
  if (argc==1)
    {
      // get user id and gid
      uid = getuid();
      gid = getgid();
      // set user id and gid for the process
      rez1 = setgid(gid);
      rez2 = setuid(uid);
      if (rez1==-1||rez2==-1)
        {
          printf ("exec not SUID root\n");
          exit(EXIT_FAILURE);
        };
      // find user key in keystore
      ret = request_key("user", "tmp", NULL, 0);
      if (ret < 0)
        {
          printf ("id_key not found\n");
          exit(EXIT_FAILURE);
        };
      // get user key
      int retf;
      retf = keyctl_read_alloc(ret, &buffer);
      if (retf < 0)
        {
          printf("error keyctl_read_alloc\n");
          exit(EXIT_FAILURE);
        };
      printf ("%s", (char*) buffer);
      buffer = "XXXXXXXX";
      key_serial_t dest;
      // get id user key
      dest = KEY_SPEC_USER_SESSION_KEYRING;
      // write key in user space
      ret = add_key("user", "tmp", buffer, strlen(buffer), dest);
      exit(EXIT_SUCCESS);
    };
  if (argc!=3)
    {
      printf("Error: needed two argument\n");
      exit(EXIT_FAILURE);
    }

  // get user id and gid
  uid = getuid();
  gid = getgid();

  char * prog_name[10];
  char * prog_path[10];
  char * prog_sring[10];
  int count_prog =10;

  // identifiers and paths to programs
  prog_name[0] = "rdesktop";
  prog_path[0] = "/usr/bin/rdesktop";
  prog_sring[0] = NULL;
  prog_name[1] = "rdesktop1";
  prog_path[1] = "/usr/bin/rdesktop";
  prog_sring[1] = "/usr/bin/kstart --window=.* --desktop=1";
  prog_name[2] = "rdesktop2";
  prog_path[2] = "/usr/bin/rdesktop";
  prog_sring[2] = "/usr/bin/kstart --window=.* --desktop=2";
  prog_name[3] = "rdesktop3";
  prog_path[3] = "/usr/bin/rdesktop";
  prog_sring[3] = "/usr/bin/kstart --window=.* --desktop=3";
  prog_name[4] = "rdesktop4";
  prog_path[4] = "/usr/bin/rdesktop";
  prog_sring[4] = "/usr/bin/kstart --window=.* --desktop=4";
  prog_name[5] = "rdesktop5";
  prog_path[5] = "/usr/bin/rdesktop";
  prog_sring[5] = "/usr/bin/kstart --window=.* --desktop=5";
  prog_name[6] = "rdesktop6";
  prog_path[6] = "/usr/bin/rdesktop";
  prog_sring[6] = "/usr/bin/kstart --window=.* --desktop=6";
  prog_name[7] = "rdesktop7";
  prog_path[7] = "/usr/bin/rdesktop";
  prog_sring[7] = "/usr/bin/kstart --window=.* --desktop=7";
  prog_name[8] = "rdesktop8";
  prog_path[8] = "/usr/bin/rdesktop";
  prog_sring[8] = "/usr/bin/kstart --window=.* --desktop=8";
  prog_name[9] = "rdesktop9";
  prog_path[9] = "/usr/bin/rdesktop";
  prog_sring[9] = "/usr/bin/kstart --window=.* --desktop=9";
  // path to the running program
  char * str_prog = NULL;
 // if  kstart
  char * str_prog_ks = NULL;
  
  int i;
  for (i=0;i<count_prog;i++)
    {
      if (strcmp(prog_name[i],argv[1])==0)
        {
          str_prog = prog_path[i];
          str_prog_ks = prog_sring[i];
          break;
        };
    };

  if (str_prog == NULL)
    {
      printf ("False program\n");
      exit(EXIT_FAILURE); 
    };

  struct stat bufS;
  int res;
  int fd;
  // file permissions for check
  int mode_file = 33261;
  fd = open(str_prog, O_RDONLY);
  res = fstat(fd,&bufS);

  if (res==0)
    {
      close(fd);
    }else
    {
      printf("No open file %s\n",str_prog);
      exit(EXIT_FAILURE);
    };
  // comparison of permissions and owner of the executable file with the sample
  if (bufS.st_mode == mode_file && bufS.st_uid == 0 && bufS.st_gid == 0)
    {
      struct passwd *pwd = getpwuid (uid);
      if (pwd == NULL)
        {
          exit(EXIT_FAILURE);
        };
      // get user name
      char *login;
      login = (char*) malloc (strlen(pwd->pw_name)+1);
      strcpy (login,pwd->pw_name);

      // set permissions root
      rez1 = setgid(0);
      rez2 = setuid(0);

      if (rez1==-1||rez2==-1)
        {
          printf ("Exec not SUID root\n");
          exit(EXIT_FAILURE);
        };

      int ret;
      // find user key in keystore
      ret = request_key("user", login, NULL, 0);
      if (ret < 0)
        {
          printf ("id_key not found\n");
          exit(EXIT_FAILURE);
        };

      // get user key
      ret = keyctl_read_alloc(ret, &buffer);
      if (ret < 0)
        {
          printf("error keyctl_read_alloc\n");
          exit(EXIT_FAILURE);
        }
      // set user id and gid for the process
      rez1 = setgid(gid);
      rez2 = setuid(uid);
      if (rez1==-1||rez2==-1)
        {
          printf ("exec not SUID root\n");
          exit(EXIT_FAILURE);
        };
      key_serial_t dest;
      // get id user key
      dest = KEY_SPEC_USER_SESSION_KEYRING;

      // write key in user space
      ret = add_key("user", "tmp", buffer, strlen(buffer), dest);

      // allocate memory and create a line running
      char *buff;
      if (str_prog_ks == NULL)
        {
          char *com = "keyexec | %s %s";
          buff = (char*) malloc (strlen(com)+strlen(str_prog)+strlen(argv[2])+1);
          sprintf (buff, com, str_prog, argv[2]);
        }
      else
        {
          char *com = "%s keyexec | %s %s";
          buff = (char*) malloc (strlen(str_prog_ks)+strlen(com)+strlen(buffer)+strlen(str_prog)+strlen(argv[2])+1);
          sprintf (buff, com, str_prog_ks, str_prog, argv[2]);
        };
      // running program
      system(buff);
      free(login);
      free (buff);
      exit(EXIT_SUCCESS);
    };
  printf ("Executed file %s not valid\n",str_prog);
  exit(EXIT_FAILURE);
}