int main(int argc, char **argv) { int c; SshCryptoStatus cs; SshCipher cipher; Boolean all_ciphers = FALSE, speed_test = FALSE, quiet = FALSE; unsigned char *iv = NULL, *key = NULL; size_t iv_len = 0, key_len = 0; char *cipher_name = NULL, *cipher_names, *hlp, *passphrase = NULL; Boolean encrypt_mode = TRUE; char *input_file = NULL, *output_file = NULL; FILE *fin, *fout; Boolean r = TRUE; if (strchr(argv[0], '/')) av0 = strrchr(argv[0], '/') + 1; else av0 = argv[0]; if (strcasecmp(av0, "ssh-encrypt") == 0) encrypt_mode = TRUE; else if (strcasecmp(av0, "ssh-decrypt") == 0) encrypt_mode = FALSE; if (ssh_crypto_library_initialize() != SSH_CRYPTO_OK) { fprintf(stderr, "Can't initialize the cryptographic provider.\n"); exit(1); } while ((c = ssh_getopt(argc, argv, "thd:ac:i:k:EDp:", NULL)) != -1) { switch (c) { case 'd': ssh_debug_set_level_string(ssh_optarg); break; case 't': speed_test = TRUE; break; case 'a': all_ciphers = TRUE; break; case 'c': cipher_name = ssh_xstrdup(ssh_optarg); break; case 'q': quiet = TRUE; break; case 'i': if (iv) { fprintf(stderr, "%s: No multiple initialization vectors allowed.\n", av0); usage(); exit(-1); } if (! hex_string_to_data(ssh_optarg, &iv, &iv_len)) { fprintf(stderr, "%s: Bad IV string.\n", av0); exit(-1); } break; case 'k': if (key) { fprintf(stderr, "%s: No multiple keys allowed.\n", av0); usage(); exit(-1); } if (! hex_string_to_data(ssh_optarg, &key, &key_len)) { fprintf(stderr, "%s: Bad KEY string.\n", av0); exit(-1); } break; case 'p': if (passphrase) { fprintf(stderr, "%s: No multiple passphrases allowed.\n", av0); usage(); exit(-1); } passphrase = ssh_optarg; break; case 'E': encrypt_mode = TRUE; break; case 'D': encrypt_mode = FALSE; break; case 'h': help_info(); usage(); exit(0); /*NOTREACHED*/ default: usage(); exit(-1); /*NOTREACHED*/ } } argc -= ssh_optind; argv += ssh_optind; if (speed_test && (argc > 0)) { fprintf(stderr, "%s: Extra parameters.\n", av0); usage(); exit(-1); /*NOTREACHED*/ } if (argc > 2) { fprintf(stderr, "%s: Extra parameters.\n", av0); usage(); exit(-1); /*NOTREACHED*/ } if (argc > 1) output_file = ssh_xstrdup(argv[1]); if (argc > 0) input_file = ssh_xstrdup(argv[0]); if ((cipher_name != NULL) && all_ciphers) { fprintf(stderr, "%s: -c and -a can't be used together.\n", av0); usage(); exit(-1); /*NOTREACHED*/ } if (all_ciphers && !speed_test) { fprintf(stderr, "%s: -a can only be used with -t.\n", av0); usage(); exit(-1); /*NOTREACHED*/ } if ((cipher_name != NULL) && strchr(cipher_name, ',') && !speed_test) { fprintf(stderr, "%s: Multiple ciphers only be used with -t.\n", av0); usage(); exit(-1); /*NOTREACHED*/ } if (cipher_name == NULL) { if (speed_test) { all_ciphers = TRUE; /* Assume `all' if test mode with no ciphers. */ } else { fprintf(stderr, "Missing -c flag.\n"); usage(); exit(-1); /*NOTREACHED*/ } } if (passphrase && key) { fprintf(stderr, "%s: Can't use both passphrase and hex key.\n", av0); usage(); exit(-1); /*NOTREACHED*/ } if (!key && !passphrase && !speed_test) { ssh_warning("%s: No key! Empty passphrase assumed.", av0); passphrase = ""; /*NOTREACHED*/ } if (speed_test) { fprintf(stderr, "Performing speed tests\n"); if (all_ciphers) { cipher_names = ssh_cipher_get_supported(); } else { /* Steal allocated cipher_name */ cipher_names = cipher_name; cipher_name = NULL; } hlp = cipher_names; while ((cipher_name = ssh_name_list_get_name(hlp)) != NULL) { hlp += strlen(cipher_name); if (*hlp == ',') hlp++; cipher_speed_test(cipher_name, passphrase, key, key_len, iv, iv_len, encrypt_mode); ssh_xfree(cipher_name); if (strlen(hlp) == 0) break; } ssh_xfree(cipher_names); } else { if (passphrase) cs = ssh_cipher_allocate_with_passphrase(cipher_name, passphrase, encrypt_mode, &cipher); else cs = ssh_cipher_allocate(cipher_name, key, key_len, encrypt_mode, &cipher); if (cs != SSH_CRYPTO_OK) { switch (cs) { case SSH_CRYPTO_UNSUPPORTED: fprintf(stderr, "%s: Unsupported cipher \"%s\".\n", av0, cipher_name); usage(); exit(-1); case SSH_CRYPTO_KEY_TOO_SHORT: fprintf(stderr, "%s: Key too short for \"%s\".\n", av0, cipher_name); usage(); exit(-1); default: fprintf(stderr, "%s: Cipher allocate failed.\n", av0); exit(-1); } /*NOTREACHED*/ } if (iv != NULL) { if (ssh_cipher_get_iv_length(ssh_cipher_name(cipher)) == iv_len) ssh_cipher_set_iv(cipher, iv); else { fprintf(stderr, "%s: Weird IV length.\n", av0); exit(-1); } } if (input_file != NULL) { fin = fopen(input_file, "r"); if (fin == NULL) { fprintf(stderr, "%s: Cannot open input file \"%s\".\n", av0, input_file); exit(-1); } } else { fin = stdin; } if (output_file != NULL) { struct stat st; if (stat(output_file, &st) >= 0) { fprintf(stderr, "%s: Output file \"%s\" exists.\n", av0, output_file); exit(-1); } fout = fopen(output_file, "w"); if (fout == NULL) { fprintf(stderr, "%s: Cannot open output file \"%s\".\n", av0, output_file); exit(-1); } } else { fout = stdout; } if (encrypt_mode) r = cipher_encrypt(cipher, fin, fout); else r = cipher_decrypt(cipher, fin, fout); if (input_file) fclose(fin); if (output_file) { fclose(fout); if (! r) (void)unlink(output_file); } ssh_cipher_free(cipher); ssh_xfree(cipher_name); } ssh_xfree(input_file); ssh_xfree(output_file); ssh_xfree(key); ssh_xfree(iv); ssh_crypto_library_uninitialize(); ssh_util_uninit(); return((r == TRUE) ? 0 : -1); }
/* Parses a given comma-separated list to tokens, which are stored in a SshDlList. The list is allocated and returned by this function. On error, returns NULL. */ SshDlList ssh_config_parse_list(char *string, SshParameterValidityProc function, void *context) { char *rest; char *current; SshDlList list; SSH_PRECOND(string != NULL); list = ssh_dllist_allocate(); rest = string; while (strlen(rest) != 0 && (current = ssh_name_list_get_name(rest)) != NULL) { char *temp; int i, j; rest += strlen(current); if (*rest == ',') rest++; /* strip whitespaces and non-printable characters */ temp = ssh_xcalloc(strlen(current) + 1, sizeof(char)); for (i = 0, j = 0; i < strlen(current) ; i ++) if(isascii(current[i]) && isprint(current[i]) && !isspace(current[i])) { temp[j] = current[i]; j++; } temp[j] = '\0'; ssh_xfree(current); current = temp; /* If validity function is given, invoke it to check the current parameter.*/ if (function) if ((*function)(current, context)) { ssh_xfree(current); continue; } if (ssh_dllist_add_item(list, (void *)current, SSH_DLLIST_END) != SSH_DLLIST_OK) { SSH_DEBUG(0, ("list operation gave error.")); ssh_dllist_rewind(list); while (ssh_dllist_is_empty(list)) { char *to_be_deleted; to_be_deleted = ssh_dllist_delete_current(list); ssh_xfree(to_be_deleted); } ssh_dllist_free(list); return NULL; } } return list; }