/* Consumes file name */ struct resource * make_pid_file_resource(struct lsh_string *file) { const char *cname = lsh_get_cstring(file); int fd; assert (cname); /* Try to open the file atomically. This provides sufficient locking * on normal (non-NFS) file systems. */ fd = open(cname, O_WRONLY | O_CREAT | O_EXCL, 0644); if (fd < 0) { if (errno != EEXIST) werror("Failed to open pid file '%S': %e.\n", file, errno); else /* FIXME: We could try to detect and ignore stale pid files. */ werror("Pid file '%S' already exists.\n", file); lsh_string_length(file); return NULL; } else { struct lsh_string *pid = ssh_format("%di", getpid()); if (!write_raw(fd, STRING_LD(pid))) { werror("Writing pidfile `%S' failed: %e\n", file, errno); /* Attempt unlinking file */ if (unlink(cname) < 0) werror("Unlinking pid file '%S' failed: %e.\n", file, errno); close(fd); lsh_string_free(pid); lsh_string_free(file); return NULL; } else { NEW(pid_file_resource, self); init_resource(&self->super, do_kill_pid_file); self->file = file; lsh_string_free(pid); close(fd); return &self->super; } } }
static struct sexp * srp_gen(struct srp_gen_options *options) { struct lsh_string *salt; struct lsh_string *name; struct sexp *e; salt = lsh_string_alloc(SALT_SIZE); RANDOM(options->r, salt->length, salt->data); name = ssh_format("%lz", options->name); e = srp_make_verifier(options->G, options->H, salt, name, options->passwd); lsh_string_free(name); return e; }
static void do_channel_forward_receive(struct ssh_channel *c, int type, struct lsh_string *data) { CAST(channel_forward, closure, c); switch (type) { case CHANNEL_DATA: A_WRITE(&closure->socket->write_buffer->super, data); break; case CHANNEL_STDERR_DATA: werror("Ignoring unexpected stderr data.\n"); lsh_string_free(data); break; default: fatal("Internal error. do_channel_forward_receive"); } }
static int write_syslog(int fd UNUSED, uint32_t length, const uint8_t *data) { struct lsh_string *s; /* Data must not contain any NUL:s */ assert(!memchr(data, '\0', length)); /* NUL-terminate the string. */ s = ssh_format("%ls", length, data); /* FIXME: Should we use different log levels for werror, verbose and * debug? */ syslog(LOG_NOTICE, "%s", lsh_get_cstring(s)); lsh_string_free(s); return 1; }
struct randomness * make_poor_random(struct hash_algorithm *hash, struct lsh_string *init) { NEW(poor_random, self); time_t now = time(NULL); #ifndef MACOS pid_t pid = getpid(); #else #ifdef __powerc pid_t pid = GetPPCTimer(); #else pid_t pid = (pid_t)TickCount(); #endif Point mouseLoc; #endif self->super.random = do_poor_random; self->super.quality = 0; self->hash = MAKE_HASH(hash); self->buffer = lsh_space_alloc(hash->hash_size); HASH_UPDATE(self->hash, sizeof(now), (UINT8 *) &now); HASH_UPDATE(self->hash, sizeof(pid), (UINT8 *) &pid); #ifdef MACOS GetMouse(&mouseLoc); HASH_UPDATE(self->hash, sizeof(mouseLoc), (UINT8 *) &mouseLoc); #endif if (init) { HASH_UPDATE(self->hash, init->length, init->data); lsh_string_free(init); } HASH_DIGEST(self->hash, self->buffer); self->pos = 0; return &self->super; }
static void connection_handle_packet(struct ssh_connection *closure, struct lsh_string *packet) { UINT8 msg; assert(!closure->paused); if (!packet->length) { werror("connection.c: Received empty packet!\n"); PROTOCOL_ERROR(closure->e, "Received empty packet."); lsh_string_free(packet); return; } if (packet->length > closure->rec_max_packet) { werror("connection.c: Packet too large!\n"); PROTOCOL_ERROR(closure->e, "Packet too large"); lsh_string_free(packet); return; } msg = packet->data[0]; debug("handle_connection: Received packet of type %i (%z)\n", msg, packet_types[msg]); switch(closure->kex_state) { case KEX_STATE_INIT: if (msg == SSH_MSG_NEWKEYS) { werror("Unexpected NEWKEYS message!\n"); PROTOCOL_ERROR(closure->e, "Unexpected NEWKEYS message!"); lsh_string_free(packet); return; } break; case KEX_STATE_IGNORE: debug("handle_connection: Ignoring packet %i\n", msg); /* It's conceivable with key exchange methods for which one * wants to switch to the NEWKEYS state immediately. But for * now, we always switch to the IN_PROGRESS state, to wait for a * KEXDH_INIT or KEXDH_REPLY message. */ closure->kex_state = KEX_STATE_IN_PROGRESS; lsh_string_free(packet); return; case KEX_STATE_IN_PROGRESS: if ( (msg == SSH_MSG_NEWKEYS) || (msg == SSH_MSG_KEXINIT)) { werror("Unexpected KEXINIT or NEWKEYS message!\n"); PROTOCOL_ERROR(closure->e, "Unexpected KEXINIT or NEWKEYS message!"); lsh_string_free(packet); return; } break; case KEX_STATE_NEWKEYS: if (! ((msg == SSH_MSG_NEWKEYS) || (msg == SSH_MSG_DISCONNECT) || (msg == SSH_MSG_IGNORE) || (msg == SSH_MSG_DEBUG))) { werror("Expected NEWKEYS message, but received message %i!\n", msg); PROTOCOL_ERROR(closure->e, "Expected NEWKEYS message"); lsh_string_free(packet); return; } break; default: fatal("handle_connection: Internal error.\n"); } HANDLE_PACKET(closure->dispatch[msg], closure, packet); lsh_string_free(packet); }
int main(int argc, char **argv) { argp_parse(&werror_argp, argc, argv, 0, NULL, NULL); { struct crypto_algorithm *algorithm = &rijndael128_algorithm; struct lsh_string *key = simple_decode_hex("00010203050607080A0B0C0D0F101112") ; struct lsh_string *plain = simple_decode_hex("506812A45F08C889B97F5980038B8359") ; struct lsh_string *cipher = simple_decode_hex("D8F532538289EF7D06B506A4FD5BE9C9") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-128 1 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-128 1 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } { struct crypto_algorithm *algorithm = &rijndael128_algorithm; struct lsh_string *key = simple_decode_hex("14151617191A1B1C1E1F202123242526") ; struct lsh_string *plain = simple_decode_hex("5C6D71CA30DE8B8B00549984D2EC7D4B") ; struct lsh_string *cipher = simple_decode_hex("59AB30F4D4EE6E4FF9907EF65B1FB68C") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-128 2 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-128 2 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } { struct crypto_algorithm *algorithm = &rijndael128_algorithm; struct lsh_string *key = simple_decode_hex("28292A2B2D2E2F30323334353738393A") ; struct lsh_string *plain = simple_decode_hex("53F3F4C64F8616E4E7C56199F48F21F6") ; struct lsh_string *cipher = simple_decode_hex("BF1ED2FCB2AF3FD41443B56D85025CB1") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-128 3 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-128 3 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } /* Skipped lots of tests */ { struct crypto_algorithm *algorithm = &rijndael128_algorithm; struct lsh_string *key = simple_decode_hex("A0A1A2A3A5A6A7A8AAABACADAFB0B1B2") ; struct lsh_string *plain = simple_decode_hex("F5F4F7F684878689A6A7A0A1D2CDCCCF") ; struct lsh_string *cipher = simple_decode_hex("CE52AF650D088CA559425223F4D32694") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-128 128 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-128 128 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } { struct crypto_algorithm *algorithm = &rijndael192_algorithm; struct lsh_string *key = simple_decode_hex("00010203050607080A0B0C0D0F10111214151617191A1B1C") ; struct lsh_string *plain = simple_decode_hex("2D33EEF2C0430A8A9EBF45E809C40BB6") ; struct lsh_string *cipher = simple_decode_hex("DFF4945E0336DF4C1C56BC700EFF837F") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-192 1 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-192 1 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } { struct crypto_algorithm *algorithm = &rijndael192_algorithm; struct lsh_string *key = simple_decode_hex("1E1F20212324252628292A2B2D2E2F30323334353738393A") ; struct lsh_string *plain = simple_decode_hex("6AA375D1FA155A61FB72353E0A5A8756") ; struct lsh_string *cipher = simple_decode_hex("B6FDDEF4752765E347D5D2DC196D1252") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-192 2 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-192 2 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } { struct crypto_algorithm *algorithm = &rijndael192_algorithm; struct lsh_string *key = simple_decode_hex("3C3D3E3F41424344464748494B4C4D4E5051525355565758") ; struct lsh_string *plain = simple_decode_hex("BC3736518B9490DCB8ED60EB26758ED4") ; struct lsh_string *cipher = simple_decode_hex("D23684E3D963B3AFCF1A114ACA90CBD6") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-192 3 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-192 3 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } /* Skipped lots of tests */ { struct crypto_algorithm *algorithm = &rijndael192_algorithm; struct lsh_string *key = simple_decode_hex("868788898B8C8D8E90919293959697989A9B9C9D9FA0A1A2") ; struct lsh_string *plain = simple_decode_hex("D3D2DDDCAAADACAF9C9D9E9FE8EBEAE5") ; struct lsh_string *cipher = simple_decode_hex("9ADB3D4CCA559BB98C3E2ED73DBF1154") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-192 128 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-192 128 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } { struct crypto_algorithm *algorithm = &rijndael256_algorithm; struct lsh_string *key = simple_decode_hex("00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526") ; struct lsh_string *plain = simple_decode_hex("834EADFCCAC7E1B30664B1ABA44815AB") ; struct lsh_string *cipher = simple_decode_hex("1946DABF6A03A2A2C3D0B05080AED6FC") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-256 1 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-256 1 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } { struct crypto_algorithm *algorithm = &rijndael256_algorithm; struct lsh_string *key = simple_decode_hex("28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E") ; struct lsh_string *plain = simple_decode_hex("D9DC4DBA3021B05D67C0518F72B62BF1") ; struct lsh_string *cipher = simple_decode_hex("5ED301D747D3CC715445EBDEC62F2FB4") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-256 2 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-256 2 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } { struct crypto_algorithm *algorithm = &rijndael256_algorithm; struct lsh_string *key = simple_decode_hex("50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576") ; struct lsh_string *plain = simple_decode_hex("A291D86301A4A739F7392173AA3C604C") ; struct lsh_string *cipher = simple_decode_hex("6585C8F43D13A6BEAB6419FC5935B9D0") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-256 3 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-256 3 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } /* Skipped lots of tests */ { struct crypto_algorithm *algorithm = &rijndael256_algorithm; struct lsh_string *key = simple_decode_hex("50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576") ; struct lsh_string *plain = simple_decode_hex("050407067477767956575051221D1C1F") ; struct lsh_string *cipher = simple_decode_hex("7444527095838FE080FC2BCDD30847EB") ; struct crypto_instance *c; assert(key->length == algorithm->key_size); assert(!algorithm->iv_size); c = MAKE_ENCRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Encrypting with rijndael-256 128 ... ", stderr); a = crypt_string(c, plain, 0); b = lsh_string_dup(cipher); if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); c = MAKE_DECRYPT(algorithm, key->data, NULL); { struct lsh_string *a, *b; fputs("Decrypting with rijndael-256 128 ... ", stderr); a = crypt_string(c, cipher, 0); b = plain; if (!lsh_string_eq(a, b)) { fputs("failed.\n", stderr);; exit(1); } fputs("ok.\n", stderr); lsh_string_free(a); lsh_string_free(b); } KILL(c); lsh_string_free(key); lsh_string_free(cipher); } return 0; }
int main(int argc, char **argv) { struct lsh_decode_key_options *options = make_lsh_decode_key_options(); struct lsh_string *input; struct lsh_string *output; int out = STDOUT_FILENO; argp_parse(&main_argp, argc, argv, 0, NULL, options); if (options->file) { out = open(lsh_get_cstring(options->file), O_WRONLY | O_CREAT, 0666); if (out < 0) { werror("Failed to open file `%S' for writing: %e.\n", options->file, errno); return EXIT_FAILURE; } } input = io_read_file_raw(STDIN_FILENO, 3000); if (!input) { werror("Failed to read stdin: %e.\n", errno); return EXIT_FAILURE; } if (options->base64) { if (!lsh_string_base64_decode(input)) { werror("Invalid base64 encoding.\n"); lsh_string_free(input); return EXIT_FAILURE; } } output = lsh_decode_key(input); lsh_string_free(input); if (!output) { werror("Invalid ssh2 key.\n"); return EXIT_FAILURE; } if (!write_raw(out, STRING_LD(output))) { werror("Write failed: %e.\n", errno); return EXIT_FAILURE; } lsh_string_free(output); gc_final(); return EXIT_SUCCESS; }
static error_t main_argp_parser(int key, char *arg, struct argp_state *state) { CAST(srp_gen_options, self, state->input); switch(key) { default: return ARGP_ERR_UNKNOWN; case ARGP_KEY_INIT: state->child_inputs[0] = &self->style; state->child_inputs[1] = NULL; break; case ARGP_KEY_END: if (!self->name) argp_error(state, "No user name given. Use the -l option, or set LOGNAME in the environment."); { struct lsh_fd *fd; if (self->file) { fd = io_write_file(self->backend, self->file->data, O_CREAT | O_EXCL | O_WRONLY, 0600, BLOCK_SIZE, NULL, self->e); if (!fd) argp_failure(state, EXIT_FAILURE, errno, "Could not open '%s'.", self->file->data); } else { fd = io_write(make_lsh_fd(self->backend, STDOUT_FILENO, "stdout", self->e), BLOCK_SIZE, NULL); } self->dest = &fd->write_buffer->super; } while (!self->passwd) { struct lsh_string *pw; struct lsh_string *again; pw = INTERACT_READ_PASSWORD(self->tty, 500, ssh_format("Enter new SRP password: "******"Aborted."); again = INTERACT_READ_PASSWORD(self->tty, 500, ssh_format("Again: "), 1); if (!again) argp_failure(state, EXIT_FAILURE, 0, "Aborted."); if (lsh_string_eq(pw, again)) self->passwd = pw; else lsh_string_free(pw); lsh_string_free(again); } if (self->style < 0) self->style = self->file ? SEXP_CANONICAL : SEXP_TRANSPORT; break; case 'o': self->file = make_string(arg); break; case 'p': self->passwd = ssh_format("%lz", arg); break; } return 0; }
static error_t main_argp_parser(int key, char *arg, struct argp_state *state) { CAST(lsh_writekey_options, self, state->input); switch(key) { default: return ARGP_ERR_UNKNOWN; case ARGP_KEY_INIT: state->child_inputs[0] = &self->style; state->child_inputs[1] = NULL; break; case ARGP_KEY_END: if (!self->file) { char *home = getenv("HOME"); struct lsh_string *s; if (!home) { argp_failure(state, EXIT_FAILURE, 0, "$HOME not set."); return EINVAL; } else { #ifndef MACOS s = ssh_format("%lz/.lsh", home); if (mkdir(lsh_get_cstring(s), 0755) < 0) { if (errno != EEXIST) argp_failure(state, EXIT_FAILURE, errno, "Creating directory %s failed.", s->data); } lsh_string_free(s); self->file = ssh_format("%lz/.lsh/identity", home); #else self->file = ssh_format("%lzidentity", home); #endif } } if (self->crypto) { if (!self->label) { const char *name = getenv("LOGNAME"); #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 300 #endif char host[MAXHOSTNAMELEN]; if (!name) { argp_failure(state, EXIT_FAILURE, 0, "LOGNAME not set. Please use the -l option."); return EINVAL; } if ( (gethostname(host, sizeof(host)) < 0) && (errno != ENAMETOOLONG) ) argp_failure(state, EXIT_FAILURE, errno, "Can't get the host name. Please use the -l option."); self->label = ssh_format("%lz@%lz", name, host); } while (!self->passphrase) { struct lsh_string *pw; struct lsh_string *again; pw = INTERACT_READ_PASSWORD(self->tty, 500, ssh_format("Enter new passphrase: "), 1); if (!pw) argp_failure(state, EXIT_FAILURE, 0, "Aborted."); again = INTERACT_READ_PASSWORD(self->tty, 500, ssh_format("Again: "), 1); if (!again) argp_failure(state, EXIT_FAILURE, 0, "Aborted."); if (lsh_string_eq(pw, again)) self->passphrase = pw; else lsh_string_free(pw); lsh_string_free(again); } } break; case 'o': self->file = make_string(arg); break; case 'i': { long i; char *end; i = strtol(arg, &end, 0); if ((end == arg) || *end || (i < 1)) { argp_failure(state, EXIT_FAILURE, 0, "Invalid iteration count."); return EINVAL; } else if (i > PKCS5_MAX_ITERATIONS) { argp_error(state, "Iteration count ridiculously large (> %d).", PKCS5_MAX_ITERATIONS); return EINVAL; } else self->iterations = i; break; } case 'c': { int name = lookup_crypto(self->crypto_algorithms, arg, &self->crypto); if (name) self->crypto_name = name; else { list_crypto_algorithms(state, self->crypto_algorithms); argp_error(state, "Unknown crypto algorithm '%s'.", arg); } break; } case 'l': self->label = ssh_format("%lz", arg); break; case 'p': self->passphrase = ssh_format("%lz", arg); break; } return 0; }
struct lsh_string * pkcs5_derive_key(struct mac_algorithm *prf, const struct lsh_string *password, const struct lsh_string *salt, uint32_t iterations, uint32_t key_length) { struct mac_instance *m = MAKE_MAC(prf, lsh_string_length(password), lsh_string_data(password)); struct lsh_string *key = lsh_string_alloc(key_length); uint32_t left = key_length; uint32_t pos = 0; /* Set up the block counter buffer. This will never have more than * the last few bits set (using sha1, 8 bits = 5100 bytes of key) so * we only change the last byte. */ uint8_t block_count[4] = { 0, 0, 0, 1 }; struct lsh_string *digest = lsh_string_alloc(prf->mac_size); struct lsh_string *buffer = lsh_string_alloc(prf->mac_size); assert(iterations); assert(key_length <= 255 * prf->mac_size); for (;; block_count[3]++) { uint32_t i; assert(block_count[3]); /* First iterate */ MAC_UPDATE(m, lsh_string_length(salt), lsh_string_data(salt)); MAC_UPDATE(m, 4, block_count); MAC_DIGEST(m, buffer, 0); for (i = 1; i < iterations; i++) { MAC_UPDATE(m, prf->mac_size, lsh_string_data(buffer)); MAC_DIGEST(m, digest, 0); lsh_string_write_xor(buffer, 0, STRING_LD(digest)); } assert(pos + left == key_length); if (left <= prf->mac_size) { lsh_string_write(key, pos, left, lsh_string_data(buffer)); break; } else { lsh_string_write_string(key, pos, buffer); pos += prf->mac_size; left -= prf->mac_size; } } KILL(m); lsh_string_free(digest); lsh_string_free(buffer); return key; }
struct lsh_string * encrypt_packet(struct lsh_string *packet, struct compress_instance *compress, struct crypto_instance *crypt, struct mac_instance *mac, uint32_t seqno) { uint32_t block_size; uint32_t new_size; uint8_t padding_length; uint32_t padding; uint32_t mac_length; uint32_t mac_start; uint32_t length = lsh_string_length(packet); assert(length); /* Deflate, pad, mac, encrypt. */ if (compress) { struct lsh_string *n = lsh_string_alloc(SSH_MAX_PACKET + SSH_MAX_PACKET_FUZZ); length = CODEC(compress, n, 0, lsh_string_length(packet), lsh_string_data(packet)); assert(length > 0); lsh_string_trunc(n, length); lsh_string_free(packet); packet = n; } block_size = crypt ? crypt->block_size : 8; mac_length = mac ? mac->mac_size : 0; /* new_size is (length + 9) rounded up to a multiple of * block_size */ new_size = block_size * (1 + (8 + length) / block_size); padding_length = new_size - length - 5; assert(padding_length >= 4); packet = ssh_format("%i%c%lfS%lr%lr", length + padding_length + 1, padding_length, packet, padding_length, &padding, mac_length, &mac_start); assert(new_size + mac_length == lsh_string_length(packet)); lsh_string_write_random(packet, padding, padding_length); if (mac) { uint8_t s[4]; assert(new_size == mac_start); WRITE_UINT32(s, seqno); MAC_UPDATE(mac, 4, s); MAC_UPDATE(mac, new_size, lsh_string_data(packet)); MAC_DIGEST(mac, packet, mac_start); } if (crypt) CRYPT(crypt, new_size, packet, 0, packet, 0); return packet; }
/* FIXME: This function is a little ugly. It would get cleaner if we * just replaced the channel's receive function pointer with NULL on * failure and do_channel_forward_receive on success. */ static void do_client_channel_x11_receive(struct ssh_channel *s, int type, struct lsh_string *data) { CAST(client_x11_channel, self, s); if (type != CHANNEL_DATA) { werror("Ignoring unexpected stderr data.\n"); lsh_string_free(data); } else switch (self->state) { case CLIENT_X11_OK: A_WRITE(&self->super.socket->write_buffer->super, data); break; fail: channel_close(&self->super.super); self->state = CLIENT_X11_DENIED; break; case CLIENT_X11_DENIED: /* Any data on the channel should be stopped before we get * here; the CHANNEL_SENT_CLOSE should be set. */ fatal("Internal error!\n"); default: { /* Copy data to buffer */ UINT32 left = self->buffer->length - self->i; /* The small initial window size should ensure that we don't get * more data. */ assert(data->length <= left); memcpy(self->buffer->data + self->i, data->data, data->length); self->i += data->length; lsh_string_free(data); switch (self->state) { case CLIENT_X11_START: /* We need byte-order, major, minor and name_length, * which is 6 octets */ if (self->i < X11_SETUP_HEADER_LENGTH) break; self->state = CLIENT_X11_GOT_LENGTHS; switch (self->buffer->data[0]) { case 'B': /* Big endian */ case 'b': /* Big endian */ self->little_endian = 0; self->name_length = READ_UINT16(self->buffer->data + 6); self->auth_length = READ_UINT16(self->buffer->data + 8); break; case 'L': /* Little endian */ case 'l': /* Little endian */ self->little_endian = 1; self->name_length = LE_READ_UINT16(self->buffer->data + 6); self->auth_length = LE_READ_UINT16(self->buffer->data + 8); break; default: werror("client_x11.c: Bad endian indicator.\n"); goto fail; } if ( (self->name_length > 20) || (self->auth_length > 16) ) { werror("client_x11.c: Too long auth name or cookie\n"); goto fail; } /* Fall through */ case CLIENT_X11_GOT_LENGTHS: { const unsigned pad_length[4] = { 0, 3, 2, 1 }; #define PAD(l) (pad_length[ (l) % 4]) UINT32 auth_offset = X11_SETUP_HEADER_LENGTH + self->name_length + PAD(self->name_length); UINT32 length = auth_offset + self->auth_length + pad_length[self->auth_length % 4]; if (self->i < length) break; debug("Received cookie of type `%ps': %xs\n", self->name_length, self->buffer->data + X11_SETUP_HEADER_LENGTH, self->auth_length, self->buffer->data + auth_offset); /* Ok, now we have the connection setup message. Check if it's ok. */ if ( (self->name_length == MIT_COOKIE_NAME_LENGTH) && !memcmp(self->buffer->data + X11_SETUP_HEADER_LENGTH, MIT_COOKIE_NAME, MIT_COOKIE_NAME_LENGTH) && lsh_string_eq_l(self->display->fake, self->auth_length, self->buffer->data + auth_offset)) { struct lsh_string *msg; UINT8 lengths[4]; static const UINT8 pad[3] = { 0, 0, 0 }; /* Cookies match! */ verbose("client_x11: Allowing X11 connection; cookies match.\n"); if (self->little_endian) { LE_WRITE_UINT16(lengths, self->display->auth_name->length); LE_WRITE_UINT16(lengths + 2, self->display->auth_data->length); } else { WRITE_UINT16(lengths, self->display->auth_name->length); WRITE_UINT16(lengths + 2, self->display->auth_data->length); } /* FIXME: Perhaps it would be easier to build the message by hand than * using ssh_format? */ /* Construct the real setup message. */ msg = ssh_format("%ls%ls%c%c%ls%ls%ls%ls", X11_SETUP_VERSION_LENGTH, self->buffer->data, 4, lengths, 0, 0, self->display->auth_name->length, self->display->auth_name->data, PAD(self->display->auth_name->length), pad, self->display->auth_data->length, self->display->auth_data->data, self->i - length, self->buffer + self->i); lsh_string_free(self->buffer); self->buffer = NULL; /* Bump window size */ channel_start_receive(&self->super.super, X11_WINDOW_SIZE - msg->length); debug("client_x11.c: Sending real X11 setup message: %xS\n", msg); /* Send real x11 connection setup message. */ A_WRITE(&self->super.socket->write_buffer->super, msg); self->state = CLIENT_X11_OK; } else { werror("client_x11: X11 connection denied; bad cookie.\n"); goto fail; } break; #undef PAD } default: fatal("Internal error. do_client_channel_x11_receive"); break; } } break; } }