/* * Decode url coding. If url_out is NULL then decode inplace, and modify url. * Otherwise return new allocated string containing the decoded buffer. Returns * TRUE if decoding was successfull and FALSE otherwise. Len is the length of * the input url and length of the returned url is in stored in the len_out * if it is not NULL. The decoded url is returned even if the decoding fails. */ Boolean ssh_url_decode_bin(char *url, size_t len, char **url_out, size_t *len_out) { char *src, *dst; unsigned int x; Boolean ok = TRUE; size_t src_len, dst_len; if (url_out != NULL) { *url_out = ssh_xmemdup(url, len); url = *url_out; } src = url; src_len = len; dst = url; dst_len = 0; while (src_len > 0) { if (*src == '%') { if (src_len >= 3 && isxdigit(src[1]) && isxdigit(src[2])) { if (isdigit(src[1])) x = src[1] - '0'; else x = tolower(src[1]) - 'a' + 10; x *= 16; if (isdigit(src[2])) x += src[2] - '0'; else x += tolower(src[2]) - 'a' + 10; *dst++ = x; dst_len++; src += 3; src_len -= 3; } else { src_len--; dst_len++; *dst++ = *src++; ok = FALSE; } } else { src_len--; dst_len++; *dst++ = *src++; } } *dst = 0; if (len_out != NULL) *len_out = dst_len; return ok; }
Boolean ssh2_key_blob_encode(unsigned long magic, const char *subject, const char *comment, const unsigned char *key, size_t keylen, unsigned char **encoded, size_t *encoded_len) { SshBufferStruct buffer; char *base64; unsigned int key_index; /* Translate to index. */ switch (magic) { case SSH_KEY_MAGIC_PUBLIC: key_index = 0; break; case SSH_KEY_MAGIC_PRIVATE: key_index = 1; break; case SSH_KEY_MAGIC_PRIVATE_ENCRYPTED: key_index = 2; break; default: return FALSE; } ssh_buffer_init(&buffer); /* Add the head for the key. */ ssh_key_blob_dump_line_str(&buffer, ssh2_pk_format_name_list[key_index].head); ssh_key_blob_dump_lf(&buffer); /* Handle key words. */ if (subject) { ssh_key_blob_dump_line_str(&buffer, "Subject: "); ssh_key_blob_dump_line_str(&buffer, subject); ssh_key_blob_dump_lf(&buffer); } if (comment) { ssh_key_blob_dump_line_str(&buffer, "Comment: "); ssh_key_blob_dump_quoted_str(&buffer, 9, comment); ssh_key_blob_dump_lf(&buffer); } /* Now add the base64 formatted stuff. */ base64 = (char *)ssh_buf_to_base64(key, keylen); ssh_key_blob_dump_str(&buffer, base64); ssh_key_blob_dump_lf(&buffer); ssh_xfree(base64); /* Add the tail for the key. */ ssh_key_blob_dump_line_str(&buffer, ssh2_pk_format_name_list[key_index].tail); ssh_key_blob_dump_lf(&buffer); *encoded_len = ssh_buffer_len(&buffer); *encoded = ssh_xmemdup(ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer)); ssh_buffer_uninit(&buffer); return TRUE; }
char *ssh_snlist_get_name(const char *namelist) { int len = ssh_snlist_name_len(namelist); char *name = NULL; if (len > 0) name = ssh_xmemdup(namelist, len); return name; }
static char * parse_img_src(char *data, size_t len) { int i; for (i = 0; i < len - 7; i++) { if ((data[i] == 's' || data[i] == 'S') && (data[i + 1] == 'r' || data[i + 1] == 'R') && (data[i + 2] == 'c' || data[i + 2] == 'C') && data[i + 3] == '=' && data[i + 4] == '"') { int start = i + 5; for (i += 6; i < len && data[i] != '"'; i++) ; return ssh_xmemdup(data + start, i - start); } } return "???"; }
/* * Parses url given in format * [<scheme>:][//[<user>[:<password>]@]<host>[:<port>]]/[<path>] * Returns true if the url is syntactically valid, false otherwise. * If the incorrect url format "www.ssh.fi" is given then returns FALSE and * sets host to contain whole url. If some piece of url is not given it is * set to NULL. If some of the pieces are not needed they can be NULL and * those pieces will be skipped. */ Boolean ssh_url_parse(const char *url, char **scheme, char **host, char **port, char **username, char **password, char **path) { const char *p, *q, *start; p = url; if (scheme) *scheme = NULL; if (host) *host = NULL; if (port) *port = NULL; if (username) *username = NULL; if (password) *password = NULL; if (path) *path = NULL; while (isspace(*p)) p++; if (!*p) { return FALSE; } start = p; while (isalpha(*p) || isdigit(*p) || *p == '+' || *p == '-' || *p == '.') p++; /* Check for scheme */ if (*p == ':') { if (scheme != NULL) *scheme = ssh_xmemdup(start, p - start); p++; start = p; } p = start; /* Do we have host name part */ if (p[0] == '/' && p[1] == '/') { start += 2; p = start; /* Check for username and password */ while (*p && *p != '@' && *p != '/') p++; if (*p == '@') { /* User name (and possible password found) */ q = p; while (q > start && *q != ':') q--; if (*q == ':') { /* Password found */ if (username != NULL) *username = ssh_xmemdup(start, q - start); if (password != NULL) *password = ssh_xmemdup(q + 1, p - (q + 1)); } else { /* Only username found */ if (username != NULL) *username = ssh_xmemdup(start, p - start); } p++; start = p; } p = start; /* Check for host name */ while (*p && *p != ':' && *p != '/') p++; if (host != NULL) *host = ssh_xmemdup(start, p - start); start = p; if (*p == ':') { start = ++p; while (isdigit(*p)) p++; if (port != NULL) *port = ssh_xmemdup(start, p - start); start = p; } } if (!*p) { return TRUE; } if (*p != '/') { if (host != NULL && *host == NULL) *host = ssh_xstrdup(p); else if (path != NULL) *path = ssh_xstrdup(p); return FALSE; } else { if (path != NULL) *path = ssh_xstrdup(p + 1); return TRUE; } }
void test_variant(const char *postfix) { SshCipher cipher; SshCryptoStatus status; unsigned char *iv, *key, *src, *plain; unsigned char *aad, *ciph, *auth_tag, digest_len; size_t key_len, iv_len, aad_len, src_len, src_len_block, ciph_len, auth_tag_len, orig_len; unsigned char *orig; unsigned char iv_buf[16], *digest; unsigned char *ciph_name; size_t blocklen; int i; for (i = 0; combined_test_vectors[i].key != NULL; i++) { hex_string_to_buf(combined_test_vectors[i].key, &key, &key_len); hex_string_to_buf(combined_test_vectors[i].iv, &iv, &iv_len); hex_string_to_buf(combined_test_vectors[i].aad, &aad, &aad_len); hex_string_to_buf(combined_test_vectors[i].plaintext, &plain, &src_len); hex_string_to_buf(combined_test_vectors[i].plaintext, &src, &src_len); orig = ssh_xmemdup(src, src_len); orig_len = src_len; hex_string_to_buf(combined_test_vectors[i].ciphertext, &ciph, &ciph_len); hex_string_to_buf(combined_test_vectors[i].auth_tag, &auth_tag, &auth_tag_len); digest = NULL; ciph_name = ssh_string_concat_2(combined_test_vectors[i].name, postfix); SSH_ASSERT(ciph_name); status = ssh_cipher_allocate(ciph_name, key, key_len, TRUE, &cipher); if (status != SSH_CRYPTO_OK) { fprintf(stderr, "Cannot allocate cipher \"%s\" (status is %s)\n", ciph_name, ssh_crypto_status_message(status)); exit(1); } if (iv_len != 12) { SSH_DEBUG(1, ("Skipping test %d with IV not equal to 12 bytes", i)); goto dealloc_and_continue; } if (!ssh_cipher_is_auth_cipher(combined_test_vectors[i].name)) { SSH_DEBUG(1, ("Skipping test %d with non-auth cipher", i)); goto dealloc_and_continue; } digest_len = ssh_cipher_auth_digest_length(combined_test_vectors[i].name); digest = ssh_xmalloc(digest_len); ssh_cipher_auth_reset(cipher); if (aad != NULL) ssh_cipher_auth_update(cipher, aad, aad_len); SSH_ASSERT(iv_len == 12); memcpy(iv_buf, iv, 12); SSH_PUT_32BIT(iv_buf + 12, 1); status = ssh_cipher_set_iv(cipher, iv_buf); SSH_VERIFY(status == SSH_CRYPTO_OK); blocklen = ssh_cipher_get_block_length(combined_test_vectors[i].name); src_len_block = src_len - (src_len % blocklen); status = ssh_cipher_transform(cipher, src, src, src_len_block); /* Process remaining bytes if test was not multiple of block size. */ if (status == SSH_CRYPTO_OK && (src_len > src_len_block)) { status = ssh_cipher_transform_remaining(cipher, src + src_len_block, src + src_len_block, src_len - src_len_block); } SSH_VERIFY(status == SSH_CRYPTO_OK); SSH_VERIFY(ssh_cipher_auth_final(cipher, digest) == SSH_CRYPTO_OK); if (src_len != ciph_len || memcmp(src, ciph, src_len)) { fprintf(stderr, "Test vectors ciphertext (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("cipher computed"), src, src_len); SSH_DEBUG_HEXDUMP(1, ("cipher expected"), ciph, ciph_len); exit(1); } if (digest_len != auth_tag_len || memcmp(digest, auth_tag, digest_len)) { fprintf(stderr, "Test vectors digest (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("digest computed"), digest, digest_len); SSH_DEBUG_HEXDUMP(1, ("digest expected"), auth_tag, auth_tag_len); exit(1); } /* Redo operation, now decryption */ ssh_cipher_free(cipher); status = ssh_cipher_allocate(ciph_name, key, key_len, FALSE, &cipher); if (status != SSH_CRYPTO_OK) { fprintf(stderr, "Cannot allocate cipher \"%s\" (status is %s)\n", ciph_name, ssh_crypto_status_message(status)); exit(1); } SSH_ASSERT(digest_len == ssh_cipher_auth_digest_length(combined_test_vectors[i].name)); ssh_cipher_auth_reset(cipher); if (aad != NULL) ssh_cipher_auth_update(cipher, aad, aad_len); SSH_ASSERT(iv_len == 12); memcpy(iv_buf, iv, 12); SSH_PUT_32BIT(iv_buf + 12, 1); status = ssh_cipher_set_iv(cipher, iv_buf); SSH_VERIFY(status == SSH_CRYPTO_OK); src_len_block = src_len - (src_len % blocklen); status = ssh_cipher_transform(cipher, orig, src, src_len_block); /* Process remaining bytes if test was not multiple of block size. */ if (status == SSH_CRYPTO_OK && (src_len > src_len_block)) { status = ssh_cipher_transform_remaining(cipher, orig + src_len_block, src + src_len_block, src_len - src_len_block); } SSH_VERIFY(status == SSH_CRYPTO_OK); SSH_VERIFY(ssh_cipher_auth_final(cipher, digest) == SSH_CRYPTO_OK); if (orig_len != ciph_len || memcmp(orig, plain, src_len)) { fprintf(stderr, "Test vectors plaintext (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("plain computed"), orig, orig_len); SSH_DEBUG_HEXDUMP(1, ("plain expected"), plain, ciph_len); exit(1); } if (digest_len != auth_tag_len || memcmp(digest, auth_tag, digest_len)) { fprintf(stderr, "Test vectors digest (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("digest computed"), digest, digest_len); SSH_DEBUG_HEXDUMP(1, ("digest expected"), auth_tag, auth_tag_len); exit(1); } /* Reset cipher and redo decryption */ ssh_cipher_auth_reset(cipher); if (aad != NULL) ssh_cipher_auth_update(cipher, aad, aad_len); status = ssh_cipher_set_iv(cipher, iv_buf); SSH_VERIFY(status == SSH_CRYPTO_OK); status = ssh_cipher_transform(cipher, orig, src, src_len_block); /* Process remaining bytes if test was not multiple of block size. */ if (status == SSH_CRYPTO_OK && (src_len > src_len_block)) { status = ssh_cipher_transform_remaining(cipher, orig + src_len_block, src + src_len_block, src_len - src_len_block); } SSH_VERIFY(status == SSH_CRYPTO_OK); SSH_VERIFY(ssh_cipher_auth_final(cipher, digest) == SSH_CRYPTO_OK); if (orig_len != ciph_len || memcmp(orig, plain, src_len)) { fprintf(stderr, "Test vectors plaintext (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("plain computed"), orig, orig_len); SSH_DEBUG_HEXDUMP(1, ("plain expected"), plain, ciph_len); exit(1); } if (digest_len != auth_tag_len || memcmp(digest, auth_tag, digest_len)) { fprintf(stderr, "Test vectors digest (ciph=%s) do not agree test=%d\n", ciph_name, i); SSH_DEBUG_HEXDUMP(1, ("digest computed"), digest, digest_len); SSH_DEBUG_HEXDUMP(1, ("digest expected"), auth_tag, auth_tag_len); exit(1); } SSH_DEBUG(2, ("Test %d (cipher=`%s') successful", i, combined_test_vectors[i].name)); dealloc_and_continue: if (cipher) ssh_cipher_free(cipher); ssh_xfree(digest); ssh_xfree(key); ssh_xfree(iv); ssh_xfree(aad); ssh_xfree(src); ssh_xfree(orig); ssh_xfree(plain); ssh_xfree(ciph); ssh_xfree(auth_tag); ssh_xfree(ciph_name); } }
Boolean ssh2_find_pgp_secret_key_internal(SshUser uc, const char *fn, const char *name, const char *fingerprint, SshUInt32 id, unsigned char **blob, size_t *blob_len, char **comment) { struct stat st; SshUserFile uf; SshFileBuffer fb; SshPgpPacket pp; Boolean found; char *key_comment = NULL; if (ssh_userfile_stat(ssh_user_uid(uc), fn, &st) < 0) { SSH_DEBUG(2, ("file %s does not exist", fn)); return FALSE; } if ((uf = ssh_userfile_open(ssh_user_uid(uc), fn, O_RDONLY, 0)) == NULL) { SSH_DEBUG(2, ("could not open %s", fn)); return FALSE; } ssh_file_buffer_init(&fb); if (ssh_file_buffer_attach_userfile(&fb, uf) == FALSE) { SSH_DEBUG(2, ("could not attach %s userfile to file buffer", fn)); ssh_userfile_close(uf); ssh_file_buffer_uninit(&fb); return FALSE; } if (fingerprint != NULL) found = ssh_pgp_find_secret_key_with_fingerprint(&fb, fingerprint, &pp, (comment ? &key_comment : NULL)); else if (name != NULL) found = ssh_pgp_find_secret_key_with_name(&fb, name, TRUE, &pp, (comment ? &key_comment : NULL)); else found = ssh_pgp_find_secret_key_with_key_id(&fb, id, &pp, (comment ? &key_comment : NULL)); ssh_file_buffer_detach(&fb); ssh_file_buffer_uninit(&fb); ssh_userfile_close(uf); if (found == FALSE) { SSH_DEBUG(2, ("pgp library didn't find secret key")); return FALSE; } *blob = ssh_xmemdup(pp->data, pp->len); if (blob_len) *blob_len = pp->len; ssh_pgp_packet_free(pp); if (comment) *comment = key_comment; return TRUE; }
/* Encodes terminal modes for the terminal referenced by fd in a portable manner, and appends the modes to a buffer being constructed. Stores constructed buffers len to buf_len. This call always succeeds, but if an error happens during encoding, buf will be empty and buf_len will be 0 */ void ssh_encode_tty_flags(int fd, unsigned char **buf, size_t *buf_len) /*void tty_make_modes(int fd)*/ { SshBuffer buffer; #ifdef USING_TERMIOS struct termios tio; #endif #ifdef USING_SGTTY struct sgttyb tio; struct tchars tiotc; struct ltchars tioltc; int tiolm; #ifdef TIOCGSTAT struct tstatus tiots; #endif /* TIOCGSTAT */ #endif /* USING_SGTTY */ int baud; if (!isatty(fd)) { SSH_TRACE(2, ("Not a tty. (fd = %d)", fd)); *buf = ssh_xstrdup(""); *buf_len = 0; return; } ssh_buffer_init(&buffer); /* Get the modes. */ #ifdef USING_TERMIOS if (tcgetattr(fd, &tio) < 0) { PUT_CHAR(TTY_OP_END); ssh_warning("tcgetattr: %.100s", strerror(errno)); goto error; } #endif /* USING_TERMIOS */ #ifdef USING_SGTTY if (ioctl(fd, TIOCGETP, &tio) < 0) { PUT_CHAR(TTY_OP_END); ssh_warning("ioctl(fd, TIOCGETP, ...): %.100s", strerror(errno)); goto error; } if (ioctl(fd, TIOCGETC, &tiotc) < 0) { PUT_CHAR(TTY_OP_END); ssh_warning("ioctl(fd, TIOCGETC, ...): %.100s", strerror(errno)); goto error; } if (ioctl(fd, TIOCLGET, &tiolm) < 0) { PUT_CHAR(TTY_OP_END); ssh_warning("ioctl(fd, TIOCLGET, ...): %.100s", strerror(errno)); goto error; } if (ioctl(fd, TIOCGLTC, &tioltc) < 0) { PUT_CHAR(TTY_OP_END); ssh_warning("ioctl(fd, TIOCGLTC, ...): %.100s", strerror(errno)); goto error; } #ifdef TIOCGSTAT if (ioctl(fd, TIOCGSTAT, &tiots) < 0) { PUT_CHAR(TTY_OP_END); ssh_warning("ioctl(fd, TIOCGSTAT, ...): %.100s", strerror(errno)); goto error; } #endif /* TIOCGSTAT */ /* termio's ECHOE is really both LCRTBS and LCRTERA - so wire them together */ if (tiolm & LCRTBS) tiolm |= LCRTERA; #endif /* USING_SGTTY */ /* Store input and output baud rates. */ baud = speed_to_baud(cfgetospeed(&tio)); PUT_CHAR(TTY_OP_OSPEED); PUT_UINT32(baud); baud = speed_to_baud(cfgetispeed(&tio)); PUT_CHAR(TTY_OP_ISPEED); PUT_UINT32(baud); /* Store values of mode flags. */ #ifdef USING_TERMIOS #define TTYCHAR(NAME, OP) \ PUT_CHAR(OP); PUT_UINT32(tio.c_cc[NAME]); #define TTYMODE(NAME, FIELD, OP) \ PUT_CHAR(OP); PUT_UINT32((tio.FIELD & NAME) != 0); #define SGTTYCHAR(NAME, OP) #define SGTTYMODE(NAME, FIELD, OP) #define SGTTYMODEN(NAME, FIELD, OP) #endif /* USING_TERMIOS */ #ifdef USING_SGTTY #define TTYCHAR(NAME, OP) #define TTYMODE(NAME, FIELD, OP) #define SGTTYCHAR(NAME, OP) \ PUT_CHAR(OP); PUT_UINT32(NAME); #define SGTTYMODE(NAME, FIELD, OP) \ PUT_CHAR(OP); PUT_UINT32((FIELD & NAME) != 0); #define SGTTYMODEN(NAME, FIELD, OP) \ PUT_CHAR(OP); PUT_UINT32((FIELD & NAME) == 0); #endif /* USING_SGTTY */ #include "sshttyflagsi.h" #undef TTYCHAR #undef TTYMODE #undef SGTTYCHAR #undef SGTTYMODE #undef SGTTYMODEN /* Mark end of mode data. */ PUT_CHAR(TTY_OP_END); *buf_len = ssh_buffer_len(&buffer); *buf = ssh_xmemdup(ssh_buffer_ptr(&buffer), *buf_len); ssh_buffer_uninit(&buffer); SSH_DEBUG_HEXDUMP(5, ("encoded tty-flags buffer"), *buf, *buf_len); return; error: ssh_buffer_uninit(&buffer); *buf = ssh_xstrdup(""); *buf_len = 0; }