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); }
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@*/ }
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; }
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; }
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); }
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() */
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; }
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); }