END_TEST START_TEST(test_filename_get_extension) { filename_t file; char *ext; ext = filename_get_extension(NULL); ck_assert_msg(ext == NULL, "A NULL filename_t has no extension."); file.name = NULL; ext = filename_get_extension(&file); ck_assert_msg(ext == NULL, "A filename_t with NULL name has no extension."); file = filename_create("frog.1txt"); ext = filename_get_extension(&file); ck_assert_msg(ext == NULL, "Invalid extension will return NULL extension."); filename_free(&file); file = filename_create("frog.txt"); ext = filename_get_extension(&file); ck_assert_str_eq(".txt", ext); ck_assert_int_eq(4, strlen(ext)); free(ext); filename_free(&file); }
bool HasGSSAPI(const UnicodeString & CustomPath) { static int has = -1; if (has < 0) { Conf * conf = conf_new(); ssh_gss_liblist * List = nullptr; { SCOPE_EXIT { ssh_gss_cleanup(List); conf_free(conf); }; Filename * filename = filename_from_str(UTF8String(CustomPath).c_str()); conf_set_filename(conf, CONF_ssh_gss_custom, filename); filename_free(filename); List = ssh_gss_setup(conf); for (intptr_t Index = 0; (has <= 0) && (Index < List->nlibraries); ++Index) { ssh_gss_library * library = &List->libraries[Index]; Ssh_gss_ctx ctx; ::ZeroMemory(&ctx, sizeof(ctx)); has = ((library->acquire_cred(library, &ctx) == SSH_GSS_OK) && (library->release_cred(library, &ctx) == SSH_GSS_OK)) ? 1 : 0; } } if (has < 0) { has = 0; } }
//--------------------------------------------------------------------------- bool __fastcall HasGSSAPI(UnicodeString CustomPath) { static int has = -1; if (has < 0) { Conf * conf = conf_new(); ssh_gss_liblist * List = NULL; try { Filename * filename = filename_from_str(UTF8String(CustomPath).c_str()); conf_set_filename(conf, CONF_ssh_gss_custom, filename); filename_free(filename); List = ssh_gss_setup(conf); for (int Index = 0; (has <= 0) && (Index < List->nlibraries); Index++) { ssh_gss_library * library = &List->libraries[Index]; Ssh_gss_ctx ctx; memset(&ctx, 0, sizeof(ctx)); has = ((library->acquire_cred(library, &ctx) == SSH_GSS_OK) && (library->release_cred(library, &ctx) == SSH_GSS_OK)) ? 1 : 0; } } __finally { ssh_gss_cleanup(List); conf_free(conf); } if (has < 0) { has = 0; } }
/* * Prompt for a key file to add, and add it. */ static void prompt_add_keyfile(void) { OPENFILENAME of; char *filelist = snewn(8192, char); if (!keypath) keypath = filereq_new(); memset(&of, 0, sizeof(of)); of.hwndOwner = hwnd; of.lpstrFilter = FILTER_KEY_FILES; of.lpstrCustomFilter = NULL; of.nFilterIndex = 1; of.lpstrFile = filelist; *filelist = '\0'; of.nMaxFile = 8192; of.lpstrFileTitle = NULL; of.lpstrTitle = "Select Private Key File"; of.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER; if (request_file(keypath, &of, TRUE, FALSE)) { if (strlen(filelist) > of.nFileOffset) { /* Only one filename returned? */ Filename *fn = filename_from_str(filelist); win_add_keyfile(fn); filename_free(fn); } else { /* we are returned a bunch of strings, end to * end. first string is the directory, the * rest the filenames. terminated with an * empty string. */ char *dir = filelist; char *filewalker = filelist + strlen(dir) + 1; while (*filewalker != '\0') { char *filename = dupcat(dir, "\\", filewalker, NULL); Filename *fn = filename_from_str(filename); win_add_keyfile(fn); filename_free(fn); sfree(filename); filewalker += strlen(filewalker) + 1; } } keylist_update(); pageant_forget_passphrases(); } sfree(filelist); }
static void gppfile(void *handle, const char *name, Conf *conf, int primary) { Filename *result = read_setting_filename(handle, name); if (!result) result = platform_default_filename(name); conf_set_filename(conf, primary, result); filename_free(result); }
/* * Free any dynamic data items pointed to by a 'struct value'. We * don't free the value itself, since it's probably part of a larger * allocated block. */ static void free_value(struct value *val, int type) { if (type == TYPE_STR) sfree(val->u.stringval); else if (type == TYPE_FILENAME) filename_free(val->u.fileval); else if (type == TYPE_FONT) fontspec_free(val->u.fontval); }
//--------------------------------------------------------------------------- TKeyType KeyType(UnicodeString FileName) { assert(ktUnopenable == SSH_KEYTYPE_UNOPENABLE); assert(ktSSHCom == SSH_KEYTYPE_SSHCOM); UTF8String UtfFileName = UTF8String(FileName); Filename * KeyFile = filename_from_str(UtfFileName.c_str()); TKeyType Result = (TKeyType)key_type(KeyFile); filename_free(KeyFile); return Result; }
TKeyType KeyType(const UnicodeString & AFileName) { assert(ktUnopenable == SSH_KEYTYPE_UNOPENABLE); assert(ktSSHCom == SSH_KEYTYPE_SSHCOM); UTF8String UtfFileName = UTF8String(AFileName); Filename * KeyFile = filename_from_str(UtfFileName.c_str()); TKeyType Result = static_cast<TKeyType>(key_type(KeyFile)); filename_free(KeyFile); return Result; }
void log_free(void *handle) { struct LogContext *ctx = (struct LogContext *)handle; logfclose(ctx); bufchain_clear(&ctx->queue); if (ctx->currlogfilename) filename_free(ctx->currlogfilename); sfree(ctx); }
TKeyType GetKeyType(const UnicodeString & AFileName) { DebugAssert(ktUnopenable == SSH_KEYTYPE_UNOPENABLE); #ifndef __linux__ DebugAssert(ktSSH2PublicOpenSSH == SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH); #endif UTF8String UtfFileName = UTF8String(::ExpandEnvironmentVariables(AFileName)); Filename * KeyFile = filename_from_str(UtfFileName.c_str()); TKeyType Result = static_cast<TKeyType>(key_type(KeyFile)); filename_free(KeyFile); return Result; }
END_TEST START_TEST(test_filename_dup) { filename_t file; file.name = NULL; filename_t dup = filename_dup(&file); ck_assert_msg(NULL == dup.name, "Duplicating a filename that has not been" " properly created should return a filename_t with a NULL name"); file = filename_create("frog"); dup = filename_dup(&file); ck_assert_str_eq("frog", dup.name); ck_assert_str_eq(file.name, dup.name); filename_free(&file); filename_free(&dup); filename_t *fileptr = NULL; dup = filename_dup(fileptr); ck_assert_msg(NULL == dup.name, "Duplicating a filename_t * that is NULL" " shall return a filename_t whoes member variable name is NULL too."); }
END_TEST START_TEST(test_filename_app) { filename_t file; // Just to check for crashes. No actual unit test. filename_app(NULL, "frog"); file = filename_create("frog"); filename_app(&file, NULL); ck_assert_str_eq("frog", file.name); filename_app(&file, ".ext"); ck_assert_str_eq("frog.ext", file.name); filename_free(&file); }
/* * Open the log file. Takes care of detecting an already-existing * file and asking the user whether they want to append, overwrite * or cancel logging. */ void logfopen(void *handle) { struct LogContext *ctx = (struct LogContext *)handle; struct tm tm; FILE *fp; int mode; /* Prevent repeat calls */ if (ctx->state != L_CLOSED) return; if (!ctx->logtype) return; tm = ltime(); /* substitute special codes in file name */ if (ctx->currlogfilename) filename_free(ctx->currlogfilename); ctx->currlogfilename = xlatlognam(conf_get_filename(ctx->conf, CONF_logfilename), conf_get_str(ctx->conf, CONF_host), conf_get_int(ctx->conf, CONF_port), &tm); #ifdef PERSOPORT test_dir( /*&*/ctx->currlogfilename ) ; #endif fp = f_open(ctx->currlogfilename, "r", FALSE); /* file already present? */ if (fp) { int logxfovr = conf_get_int(ctx->conf, CONF_logxfovr); fclose(fp); if (logxfovr != LGXF_ASK) { mode = ((logxfovr == LGXF_OVR) ? 2 : 1); } else mode = askappend(ctx->frontend, ctx->currlogfilename, logfopen_callback, ctx); } else mode = 2; /* create == overwrite */ if (mode < 0) ctx->state = L_OPENING; else logfopen_callback(ctx, mode); /* open the file */ }
END_TEST START_TEST(test_filename_has_extension) { filename_t file; file.name = NULL; ck_assert_int_eq(0, filename_has_extension(NULL)); ck_assert_int_eq(0, filename_has_extension(&file)); file = filename_create("frog"); ck_assert_int_eq(0, filename_has_extension(&file)); filename_free(&file); file = filename_create("..out"); ck_assert_int_eq(1, filename_has_extension(&file)); filename_free(&file); file = filename_create("frog.1out"); ck_assert_int_eq(0, filename_has_extension(&file)); filename_free(&file); file = filename_create("frog."); ck_assert_int_eq(0, filename_has_extension(&file)); filename_free(&file); file = filename_create("frog.text"); ck_assert_int_eq(1, filename_has_extension(&file)); filename_free(&file); file = filename_create("frog.te"); ck_assert_int_eq(0, filename_has_extension(&file)); filename_free(&file); file = filename_create(".txt"); ck_assert_int_eq(0, filename_has_extension(&file)); filename_free(&file); }
int main(int argc, char **argv) { int *fdlist; int fd; int i, fdstate; size_t fdsize; unsigned long now; ssh_key **hostkeys = NULL; size_t nhostkeys = 0, hostkeysize = 0; RSAKey *hostkey1 = NULL; AuthPolicy ap; Conf *conf = conf_new(); load_open_settings(NULL, conf); ap.kbdint_state = 0; ap.ssh1keys = NULL; ap.ssh2keys = NULL; if (argc <= 1) { /* * We're going to terminate with an error message below, * because there are no host keys. But we'll display the help * as additional standard-error output, if nothing else so * that people see the giant safety warning. */ show_help(stderr); fputc('\n', stderr); } while (--argc > 0) { const char *arg = *++argv; const char *val; if (!strcmp(arg, "--help")) { show_help(stdout); exit(0); } else if (!strcmp(arg, "--version")) { show_version_and_exit(); } else if (!strcmp(arg, "--verbose") || !strcmp(arg, "-v")) { verbose = true; } else if (longoptarg(arg, "--hostkey", &val, &argc, &argv)) { Filename *keyfile; int keytype; const char *error; keyfile = filename_from_str(val); keytype = key_type(keyfile); if (keytype == SSH_KEYTYPE_SSH2) { ssh2_userkey *uk; ssh_key *key; uk = ssh2_load_userkey(keyfile, NULL, &error); filename_free(keyfile); if (!uk || !uk->key) { fprintf(stderr, "%s: unable to load host key '%s': " "%s\n", appname, val, error); exit(1); } char *invalid = ssh_key_invalid(uk->key, 0); if (invalid) { fprintf(stderr, "%s: host key '%s' is unusable: " "%s\n", appname, val, invalid); exit(1); } key = uk->key; sfree(uk->comment); sfree(uk); for (i = 0; i < nhostkeys; i++) if (ssh_key_alg(hostkeys[i]) == ssh_key_alg(key)) { fprintf(stderr, "%s: host key '%s' duplicates key " "type %s\n", appname, val, ssh_key_alg(key)->ssh_id); exit(1); } sgrowarray(hostkeys, hostkeysize, nhostkeys); hostkeys[nhostkeys++] = key; } else if (keytype == SSH_KEYTYPE_SSH1) { if (hostkey1) { fprintf(stderr, "%s: host key '%s' is a redundant " "SSH-1 host key\n", appname, val); exit(1); } hostkey1 = snew(RSAKey); if (!rsa_ssh1_loadkey(keyfile, hostkey1, NULL, &error)) { fprintf(stderr, "%s: unable to load host key '%s': " "%s\n", appname, val, error); exit(1); } } else { fprintf(stderr, "%s: '%s' is not loadable as a " "private key (%s)", appname, val, key_type_to_str(keytype)); exit(1); } } else if (longoptarg(arg, "--userkey", &val, &argc, &argv)) { Filename *keyfile; int keytype; const char *error; keyfile = filename_from_str(val); keytype = key_type(keyfile); if (keytype == SSH_KEYTYPE_SSH2_PUBLIC_RFC4716 || keytype == SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH) { strbuf *sb = strbuf_new(); struct AuthPolicy_ssh2_pubkey *node; void *blob; if (!ssh2_userkey_loadpub(keyfile, NULL, BinarySink_UPCAST(sb), NULL, &error)) { fprintf(stderr, "%s: unable to load user key '%s': " "%s\n", appname, val, error); exit(1); } node = snew_plus(struct AuthPolicy_ssh2_pubkey, sb->len); blob = snew_plus_get_aux(node); memcpy(blob, sb->u, sb->len); node->public_blob = make_ptrlen(blob, sb->len); node->next = ap.ssh2keys; ap.ssh2keys = node; strbuf_free(sb); } else if (keytype == SSH_KEYTYPE_SSH1_PUBLIC) {
int main(int argc, char **argv) { Filename *infilename = NULL; int intype = SSH_KEYTYPE_UNOPENABLE; int encrypted = 0; char* origcomment = 0; char* line = 0; char* passphrase = 0; struct ssh2_userkey *ssh2key = NULL; char* fingerprint = 0; printf("fzputtygen\n"); printf("Copyright (C) 2008-2016 Tim Kosse\n"); printf("Based on PuTTY's puttygen\n"); printf("Copyright (C) 1997-2015 Simon Tatham and the PuTTY team\n"); printf("Converts private SSH keys into PuTTY's format.\n"); printf("This program is used by FileZilla and not intended to be used directly.\n"); printf("Use the puttygen tool from PuTTY for a human-usable tool.\n"); printf("\n"); fflush(stdout); while (1) { sfree(line); line = fgetline(stdin); if (!line || !*line || *line == '\n') break; line[strlen(line) - 1] = 0; char* cmd = line, *args = line; while (*args) { if (*args == ' ') { *(args++) = 0; break; } args++; } if (!*args) args = 0; if (!strcmp(cmd, "file")) { char const* ret = NULL; if (ssh2key) { ssh2key->alg->freekey(ssh2key->data); sfree(ssh2key); ssh2key = 0; } sfree(passphrase); passphrase = 0; sfree(fingerprint); fingerprint = 0; if (!args) { fzprintf(sftpError, "No argument given"); continue; } if (infilename) { filename_free(infilename); } infilename = filename_from_str(args); intype = key_type(infilename); switch (intype) { case SSH_KEYTYPE_SSH1: ret = "incompatible"; intype = SSH_KEYTYPE_UNOPENABLE; break; case SSH_KEYTYPE_SSH2: ret = "ok"; encrypted = ssh2_userkey_encrypted(infilename, &origcomment); break; case SSH_KEYTYPE_UNKNOWN: case SSH_KEYTYPE_UNOPENABLE: default: ret = "error"; intype = SSH_KEYTYPE_UNOPENABLE; break; case SSH_KEYTYPE_OPENSSH_PEM: case SSH_KEYTYPE_OPENSSH_NEW: case SSH_KEYTYPE_SSHCOM: encrypted = import_encrypted(infilename, intype, &origcomment); ret = encrypted ? "convertible" : "ok"; break; } fzprintf(sftpReply, "%s", ret); } else if (!strcmp(cmd, "encrypted")) { if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No key file opened"); continue; } fzprintf(sftpReply, "%d", encrypted ? 1 : 0); } else if (!strcmp(cmd, "comment")) { if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No key file opened"); continue; } if (ssh2key && ssh2key->comment) { fzprintf(sftpReply, "%s", ssh2key->comment); } else if (origcomment) fzprintf(sftpReply, "%s", origcomment); else fzprintf(sftpReply, ""); } else if (!strcmp(cmd, "password")) { const char* error = NULL; if (!args) { fzprintf(sftpError, "No argument given"); continue; } if (intype == SSH_KEYTYPE_UNOPENABLE) { fzprintf(sftpError, "No key file opened"); continue; } if (!encrypted) { fzprintf(sftpError, "File is not encrypted"); continue; } if (ssh2key) { fzprintf(sftpError, "Already opened file"); continue; } sfree(passphrase); passphrase = strdup(args); switch (intype) { case SSH_KEYTYPE_SSH2: ssh2key = ssh2_load_userkey(infilename, passphrase, &error); break; case SSH_KEYTYPE_OPENSSH_PEM: case SSH_KEYTYPE_OPENSSH_NEW: case SSH_KEYTYPE_SSHCOM: ssh2key = import_ssh2(infilename, intype, passphrase, &error); break; default: break; } if (ssh2key == SSH2_WRONG_PASSPHRASE) { error = "wrong passphrase"; ssh2key = 0; } if (ssh2key) { error = NULL; } else if (!error) { error = "unknown error"; } if (error) fzprintf(sftpError, "Error loading file: %s", error); else fzprintf(sftpReply, ""); } else if (!strcmp(cmd, "fingerprint")) { const char* error = 0; if (!fingerprint) { if (ssh2key) { fingerprint = ssh2_fingerprint(ssh2key->alg, ssh2key->data); } else { switch (intype) { case SSH_KEYTYPE_SSH2: { void* ssh2blob; int bloblen = 0; char* comment = NULL; ssh2blob = ssh2_userkey_loadpub(infilename, 0, &bloblen, &comment, &error); if (ssh2blob) { fingerprint = ssh2_fingerprint_blob(ssh2blob, bloblen); sfree(ssh2blob); } else if (!error) { error = "unknown error"; } if (comment) { sfree(origcomment); origcomment = comment; } break; } case SSH_KEYTYPE_OPENSSH_PEM: case SSH_KEYTYPE_OPENSSH_NEW: case SSH_KEYTYPE_SSHCOM: ssh2key = import_ssh2(infilename, intype, "", &error); if (ssh2key) { if (ssh2key != SSH2_WRONG_PASSPHRASE) { error = NULL; fingerprint = ssh2_fingerprint(ssh2key->alg, ssh2key->data); } else { ssh2key = NULL; error = "wrong passphrase"; } } else if (!error) error = "unknown error"; break; default: error = "No file loaded"; break; } } } if (!fingerprint && !error) { error = "Could not get fingerprint"; } if (error) fzprintf(sftpError, "Error loading file: %s", error); else fzprintf(sftpReply, "%s", fingerprint); } else if (!strcmp(cmd, "write")) { Filename* outfilename; int ret; if (!args) { fzprintf(sftpError, "No argument given"); continue; } if (!ssh2key) { fzprintf(sftpError, "No key loaded"); continue; } outfilename = filename_from_str(args); ret = ssh2_save_userkey(outfilename, ssh2key, passphrase); if (!ret) { fzprintf(sftpError, "Unable to save SSH-2 private key"); continue; } filename_free(outfilename); fzprintf(sftpReply, ""); } else fzprintf(sftpError, "Unknown command"); } if (infilename) { filename_free(infilename); } sfree(line); sfree(passphrase); if (ssh2key) { ssh2key->alg->freekey(ssh2key->data); sfree(ssh2key); } sfree(fingerprint); sfree(origcomment); return 0; }
/* * Dialog-box function for the main PuTTYgen dialog box. */ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static const char generating_msg[] = "Please wait while a key is generated..."; static const char entropy_msg[] = "Please generate some randomness by moving the mouse over the blank area."; struct MainDlgState *state; switch (msg) { case WM_INITDIALOG: if (has_help()) SetWindowLongPtr(hwnd, GWL_EXSTYLE, GetWindowLongPtr(hwnd, GWL_EXSTYLE) | WS_EX_CONTEXTHELP); else { /* * If we add a Help button, this is where we destroy it * if the help file isn't present. */ } SendMessage(hwnd, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadIcon(hinst, MAKEINTRESOURCE(200))); state = snew(struct MainDlgState); state->generation_thread_exists = FALSE; state->collecting_entropy = FALSE; state->entropy = NULL; state->key_exists = FALSE; SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) state); { HMENU menu, menu1; menu = CreateMenu(); menu1 = CreateMenu(); AppendMenu(menu1, MF_ENABLED, IDC_LOAD, "&Load private key"); AppendMenu(menu1, MF_ENABLED, IDC_SAVEPUB, "Save p&ublic key"); AppendMenu(menu1, MF_ENABLED, IDC_SAVE, "&Save private key"); AppendMenu(menu1, MF_SEPARATOR, 0, 0); AppendMenu(menu1, MF_ENABLED, IDC_QUIT, "E&xit"); AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&File"); state->filemenu = menu1; menu1 = CreateMenu(); AppendMenu(menu1, MF_ENABLED, IDC_GENERATE, "&Generate key pair"); AppendMenu(menu1, MF_SEPARATOR, 0, 0); AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH1, "SSH-&1 key (RSA)"); AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2RSA, "SSH-2 &RSA key"); AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2DSA, "SSH-2 &DSA key"); AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2ECDSA, "SSH-2 &ECDSA key"); AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&Key"); state->keymenu = menu1; menu1 = CreateMenu(); AppendMenu(menu1, MF_ENABLED, IDC_IMPORT, "&Import key"); AppendMenu(menu1, MF_SEPARATOR, 0, 0); AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH, "Export &OpenSSH key"); AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_SSHCOM, "Export &ssh.com key"); AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "Con&versions"); state->cvtmenu = menu1; menu1 = CreateMenu(); AppendMenu(menu1, MF_ENABLED, IDC_ABOUT, "&About"); if (has_help()) AppendMenu(menu1, MF_ENABLED, IDC_GIVEHELP, "&Help"); AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&Help"); SetMenu(hwnd, menu); } /* * Centre the window. */ { /* centre the window */ RECT rs, rd; HWND hw; hw = GetDesktopWindow(); if (GetWindowRect(hw, &rs) && GetWindowRect(hwnd, &rd)) MoveWindow(hwnd, (rs.right + rs.left + rd.left - rd.right) / 2, (rs.bottom + rs.top + rd.top - rd.bottom) / 2, rd.right - rd.left, rd.bottom - rd.top, TRUE); } { struct ctlpos cp, cp2; /* Accelerators used: acglops1rbde */ ctlposinit(&cp, hwnd, 4, 4, 4); beginbox(&cp, "Key", IDC_BOX_KEY); cp2 = cp; statictext(&cp2, "No key.", 1, IDC_NOKEY); cp2 = cp; statictext(&cp2, "", 1, IDC_GENERATING); progressbar(&cp2, IDC_PROGRESS); bigeditctrl(&cp, "&Public key for pasting into authorized_keys file:", IDC_PKSTATIC, IDC_KEYDISPLAY, 5); SendDlgItemMessage(hwnd, IDC_KEYDISPLAY, EM_SETREADONLY, 1, 0); staticedit(&cp, "Key f&ingerprint:", IDC_FPSTATIC, IDC_FINGERPRINT, 75); SendDlgItemMessage(hwnd, IDC_FINGERPRINT, EM_SETREADONLY, 1, 0); staticedit(&cp, "Key &comment:", IDC_COMMENTSTATIC, IDC_COMMENTEDIT, 75); staticpassedit(&cp, "Key p&assphrase:", IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT, 75); staticpassedit(&cp, "C&onfirm passphrase:", IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT, 75); endbox(&cp); beginbox(&cp, "Actions", IDC_BOX_ACTIONS); staticbtn(&cp, "Generate a public/private key pair", IDC_GENSTATIC, "&Generate", IDC_GENERATE); staticbtn(&cp, "Load an existing private key file", IDC_LOADSTATIC, "&Load", IDC_LOAD); static2btn(&cp, "Save the generated key", IDC_SAVESTATIC, "Save p&ublic key", IDC_SAVEPUB, "&Save private key", IDC_SAVE); endbox(&cp); beginbox(&cp, "Parameters", IDC_BOX_PARAMS); radioline(&cp, "Type of key to generate:", IDC_TYPESTATIC, 4, "SSH-&1 (RSA)", IDC_KEYSSH1, "SSH-2 &RSA", IDC_KEYSSH2RSA, "SSH-2 &DSA", IDC_KEYSSH2DSA, "SSH-2 &ECDSA", IDC_KEYSSH2ECDSA, NULL); staticedit(&cp, "Number of &bits in a generated key:", IDC_BITSSTATIC, IDC_BITS, 20); endbox(&cp); } CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2ECDSA, IDC_KEYSSH2RSA); CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2ECDSA, IDC_KEYSSH2RSA, MF_BYCOMMAND); SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEYSIZE, FALSE); /* * Initially, hide the progress bar and the key display, * and show the no-key display. Also disable the Save * buttons, because with no key we obviously can't save * anything. */ ui_set_state(hwnd, state, 0); /* * Load a key file if one was provided on the command line. */ if (cmdline_keyfile) { Filename *fn = filename_from_str(cmdline_keyfile); load_key_file(hwnd, state, fn, 0); filename_free(fn); } return 1; case WM_MOUSEMOVE: state = (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA); if (state->collecting_entropy && state->entropy && state->entropy_got < state->entropy_required) { state->entropy[state->entropy_got++] = lParam; state->entropy[state->entropy_got++] = GetMessageTime(); SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, state->entropy_got, 0); if (state->entropy_got >= state->entropy_required) { struct rsa_key_thread_params *params; DWORD threadid; /* * Seed the entropy pool */ random_add_heavynoise(state->entropy, state->entropy_size); smemclr(state->entropy, state->entropy_size); sfree(state->entropy); state->collecting_entropy = FALSE; SetDlgItemText(hwnd, IDC_GENERATING, generating_msg); SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, PROGRESSRANGE)); SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, 0, 0); params = snew(struct rsa_key_thread_params); params->progressbar = GetDlgItem(hwnd, IDC_PROGRESS); params->dialog = hwnd; params->keysize = state->keysize; params->keytype = state->keytype; params->key = &state->key; params->dsskey = &state->dsskey; if (!CreateThread(NULL, 0, generate_rsa_key_thread, params, 0, &threadid)) { MessageBox(hwnd, "Out of thread resources", "Key generation error", MB_OK | MB_ICONERROR); sfree(params); } else { state->generation_thread_exists = TRUE; } } } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_KEYSSH1: case IDC_KEYSSH2RSA: case IDC_KEYSSH2DSA: case IDC_KEYSSH2ECDSA: { state = (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA); if (!IsDlgButtonChecked(hwnd, LOWORD(wParam))) CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2DSA, LOWORD(wParam)); CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2DSA, LOWORD(wParam), MF_BYCOMMAND); CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2ECDSA, LOWORD(wParam)); CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2ECDSA, LOWORD(wParam), MF_BYCOMMAND); } break; case IDC_QUIT: PostMessage(hwnd, WM_CLOSE, 0, 0); break; case IDC_COMMENTEDIT: if (HIWORD(wParam) == EN_CHANGE) { state = (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA); if (state->key_exists) { HWND editctl = GetDlgItem(hwnd, IDC_COMMENTEDIT); int len = GetWindowTextLength(editctl); if (*state->commentptr) sfree(*state->commentptr); *state->commentptr = snewn(len + 1, char); GetWindowText(editctl, *state->commentptr, len + 1); if (state->ssh2) { setupbigedit2(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC, &state->ssh2key); } else { setupbigedit1(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC, &state->key); } } }
int cmdline_process_param(const char *p, char *value, int need_save, Conf *conf) { int ret = 0; if (p[0] != '-') { if (need_save < 0) return 0; /* * Common handling for the tools whose initial command-line * arguments specify a hostname to connect to, i.e. PuTTY and * Plink. Doesn't count the file transfer tools, because their * hostname specification appears as part of a more * complicated scheme. */ if ((cmdline_tooltype & TOOLTYPE_HOST_ARG) && !seen_hostname_argument && (!(cmdline_tooltype & TOOLTYPE_HOST_ARG_FROM_LAUNCHABLE_LOAD) || !loaded_session || !conf_launchable(conf))) { /* * Treat this argument as a host name, if we have not yet * seen a host name argument or -load. * * Exception, in some tools (Plink): if we have seen -load * but it didn't create a launchable session, then we * still accept a hostname argument following that -load. * This allows you to make saved sessions that configure * lots of other stuff (colour schemes, terminal settings * etc) and then say 'putty -load sessionname hostname'. * * Also, we carefully _don't_ test conf for launchability * if we haven't been explicitly told to load a session * (otherwise saving a host name into Default Settings * would cause 'putty' on its own to immediately launch * the default session and never be able to do anything * else). */ if (!strncmp(p, "telnet:", 7)) { /* * If the argument starts with "telnet:", set the * protocol to Telnet and process the string as a * Telnet URL. */ /* * Skip the "telnet:" or "telnet://" prefix. */ p += 7; if (p[0] == '/' && p[1] == '/') p += 2; conf_set_int(conf, CONF_protocol, PROT_TELNET); /* * The next thing we expect is a host name. */ { const char *host = p; char *buf; p += host_strcspn(p, ":/"); buf = dupprintf("%.*s", (int)(p - host), host); conf_set_str(conf, CONF_host, buf); sfree(buf); seen_hostname_argument = true; } /* * If the host name is followed by a colon, then * expect a port number after it. */ if (*p == ':') { p++; conf_set_int(conf, CONF_port, atoi(p)); /* * Set the flag that will stop us from treating * the next argument as a separate port; this one * counts as explicitly provided. */ seen_port_argument = true; } else { conf_set_int(conf, CONF_port, -1); } } else { char *user = NULL, *hostname = NULL; const char *hostname_after_user; int port_override = -1; size_t len; /* * Otherwise, treat it as a bare host name. */ if (cmdline_tooltype & TOOLTYPE_HOST_ARG_PROTOCOL_PREFIX) { /* * Here Plink checks for a comma-separated * protocol prefix, e.g. 'ssh,hostname' or * 'ssh,user@hostname'. * * I'm not entirely sure why; this behaviour dates * from 2000 and isn't explained. But I _think_ it * has to do with CVS transport or similar use * cases, in which the end user invokes the SSH * client indirectly, via some means that only * lets them pass a single string argument, and it * was occasionally useful to shoehorn the choice * of protocol into that argument. */ const char *comma = strchr(p, ','); if (comma) { char *prefix = dupprintf("%.*s", (int)(comma - p), p); const struct BackendVtable *vt = backend_vt_from_name(prefix); if (vt) { default_protocol = vt->protocol; conf_set_int(conf, CONF_protocol, default_protocol); port_override = vt->default_port; } else { cmdline_error("unrecognised protocol prefix '%s'", prefix); } sfree(prefix); p = comma + 1; } } hostname_after_user = p; if (cmdline_tooltype & TOOLTYPE_HOST_ARG_CAN_BE_SESSION) { /* * If the hostname argument can also be a saved * session (see below), then here we also check * for a user@ prefix, which will override the * username from the saved session. * * (If the hostname argument _isn't_ a saved * session, we don't do this.) */ const char *at = strrchr(p, '@'); if (at) { user = dupprintf("%.*s", (int)(at - p), p); hostname_after_user = at + 1; } } /* * Write the whole hostname argument (minus only that * optional protocol prefix) into the existing Conf, * for tools that don't treat it as a saved session * and as a fallback for those that do. */ hostname = dupstr(p + strspn(p, " \t")); len = strlen(hostname); while (len > 0 && (hostname[len-1] == ' ' || hostname[len-1] == '\t')) hostname[--len] = '\0'; seen_hostname_argument = true; conf_set_str(conf, CONF_host, hostname); if ((cmdline_tooltype & TOOLTYPE_HOST_ARG_CAN_BE_SESSION) && !loaded_session) { /* * For some tools, we equivocate between a * hostname argument and an argument naming a * saved session. Here we attempt to load a * session with the specified name, and if that * session exists and is launchable, we overwrite * the entire Conf with it. * * We skip this check if a -load option has * already happened, so that * * plink -load non-launchable-session hostname * * will treat 'hostname' as a hostname _even_ if a * saved session called 'hostname' exists. (This * doesn't lose any functionality someone could * have needed, because if 'hostname' did cause a * session to be loaded, then it would overwrite * everything from the previously loaded session. * So if that was the behaviour someone wanted, * then they could get it by leaving off the * -load completely.) */ Conf *conf2 = conf_new(); if (do_defaults(hostname_after_user, conf2) && conf_launchable(conf2)) { conf_copy_into(conf, conf2); loaded_session = true; /* And override the username if one was given. */ if (user) conf_set_str(conf, CONF_username, user); } conf_free(conf2); } sfree(hostname); sfree(user); if (port_override >= 0) conf_set_int(conf, CONF_port, port_override); } return 1; } else if ((cmdline_tooltype & TOOLTYPE_PORT_ARG) && !seen_port_argument) { /* * If we've already got a host name from the command line * (either as a hostname argument or a qualifying -load), * but not a port number, then treat the next argument as * a port number. * * We handle this by calling ourself recursively to * pretend we received a -P argument, so that it will be * deferred until it's a good moment to run it. */ char *dup = dupstr(p); /* 'value' is not a const char * */ int retd = cmdline_process_param("-P", dup, 1, conf); sfree(dup); assert(retd == 2); seen_port_argument = true; return 1; } else { /* * Refuse to recognise this argument, and give it back to * the tool's own command-line processing. */ return 0; } } #ifdef PUTTYNG if (!stricmp(p, "-hwndparent")) { RETURN(2); hwnd_parent = atoi(value); return 2; } #endif if (!strcmp(p, "-load")) { RETURN(2); /* This parameter must be processed immediately rather than being * saved. */ do_defaults(value, conf); loaded_session = true; cmdline_session_name = dupstr(value); return 2; } if (!strcmp(p, "-ssh")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); default_protocol = PROT_SSH; default_port = 22; conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_port, default_port); return 1; } if (!strcmp(p, "-telnet")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); default_protocol = PROT_TELNET; default_port = 23; conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_port, default_port); return 1; } if (!strcmp(p, "-rlogin")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); default_protocol = PROT_RLOGIN; default_port = 513; conf_set_int(conf, CONF_protocol, default_protocol); conf_set_int(conf, CONF_port, default_port); return 1; } if (!strcmp(p, "-raw")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); default_protocol = PROT_RAW; conf_set_int(conf, CONF_protocol, default_protocol); } if (!strcmp(p, "-serial")) { RETURN(1); /* Serial is not NONNETWORK in an odd sense of the word */ UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); default_protocol = PROT_SERIAL; conf_set_int(conf, CONF_protocol, default_protocol); /* The host parameter will already be loaded into CONF_host, * so copy it across */ conf_set_str(conf, CONF_serline, conf_get_str(conf, CONF_host)); } if (!strcmp(p, "-v")) { RETURN(1); flags |= FLAG_VERBOSE; } if (!strcmp(p, "-l")) { RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_str(conf, CONF_username, value); } if (!strcmp(p, "-loghost")) { RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_str(conf, CONF_loghost, value); } if (!strcmp(p, "-hostkey")) { char *dup; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); dup = dupstr(value); if (!validate_manual_hostkey(dup)) { cmdline_error("'%s' is not a valid format for a manual host " "key specification", value); sfree(dup); return ret; } conf_set_str_str(conf, CONF_ssh_manual_hostkeys, dup, ""); sfree(dup); } if ((!strcmp(p, "-L") || !strcmp(p, "-R") || !strcmp(p, "-D"))) { char type, *q, *qq, *key, *val; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); if (strcmp(p, "-D")) { /* * For -L or -R forwarding types: * * We expect _at least_ two colons in this string. The * possible formats are `sourceport:desthost:destport', * or `sourceip:sourceport:desthost:destport' if you're * specifying a particular loopback address. We need to * replace the one between source and dest with a \t; * this means we must find the second-to-last colon in * the string. * * (This looks like a foolish way of doing it given the * existence of strrchr, but it's more efficient than * two strrchrs - not to mention that the second strrchr * would require us to modify the input string!) */ type = p[1]; /* 'L' or 'R' */ q = qq = host_strchr(value, ':'); while (qq) { char *qqq = host_strchr(qq+1, ':'); if (qqq) q = qq; qq = qqq; } if (!q) { cmdline_error("-%c expects at least two colons in its" " argument", type); return ret; } key = dupprintf("%c%.*s", type, (int)(q - value), value); val = dupstr(q+1); } else { /* * Dynamic port forwardings are entered under the same key * as if they were local (because they occupy the same * port space - a local and a dynamic forwarding on the * same local port are mutually exclusive), with the * special value "D" (which can be distinguished from * anything in the ordinary -L case by containing no * colon). */ key = dupprintf("L%s", value); val = dupstr("D"); } conf_set_str_str(conf, CONF_portfwd, key, val); sfree(key); sfree(val); } if ((!strcmp(p, "-nc"))) { char *host, *portp; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); portp = host_strchr(value, ':'); if (!portp) { cmdline_error("-nc expects argument of form 'host:port'"); return ret; } host = dupprintf("%.*s", (int)(portp - value), value); conf_set_str(conf, CONF_ssh_nc_host, host); conf_set_int(conf, CONF_ssh_nc_port, atoi(portp + 1)); sfree(host); } if (!strcmp(p, "-m")) { const char *filename; FILE *fp; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); filename = value; fp = fopen(filename, "r"); if (!fp) { cmdline_error("unable to open command file \"%s\"", filename); return ret; } strbuf *command = strbuf_new(); char readbuf[4096]; while (1) { size_t nread = fread(readbuf, 1, sizeof(readbuf), fp); if (nread == 0) break; put_data(command, readbuf, nread); } fclose(fp); conf_set_str(conf, CONF_remote_cmd, command->s); conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_bool(conf, CONF_nopty, true); /* command => no terminal */ strbuf_free(command); } if (!strcmp(p, "-P")) { RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(1); /* lower priority than -ssh,-telnet */ conf_set_int(conf, CONF_port, atoi(value)); } if (!strcmp(p, "-pw")) { RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(1); /* We delay evaluating this until after the protocol is decided, * so that we can warn if it's of no use with the selected protocol */ if (conf_get_int(conf, CONF_protocol) != PROT_SSH) cmdline_error("the -pw option can only be used with the " "SSH protocol"); else { cmdline_password = dupstr(value); /* Assuming that `value' is directly from argv, make a good faith * attempt to trample it, to stop it showing up in `ps' output * on Unix-like systems. Not guaranteed, of course. */ smemclr(value, strlen(value)); } } if (!strcmp(p, "-agent") || !strcmp(p, "-pagent") || !strcmp(p, "-pageant")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_tryagent, true); } if (!strcmp(p, "-noagent") || !strcmp(p, "-nopagent") || !strcmp(p, "-nopageant")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_tryagent, false); } if (!strcmp(p, "-share")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_ssh_connection_sharing, true); } if (!strcmp(p, "-noshare")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_ssh_connection_sharing, false); } if (!strcmp(p, "-A")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_agentfwd, true); } if (!strcmp(p, "-a")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_agentfwd, false); } if (!strcmp(p, "-X")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_x11_forward, true); } if (!strcmp(p, "-x")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_x11_forward, false); } if (!strcmp(p, "-t")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(1); /* lower priority than -m */ conf_set_bool(conf, CONF_nopty, false); } if (!strcmp(p, "-T")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(1); conf_set_bool(conf, CONF_nopty, true); } if (!strcmp(p, "-N")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_ssh_no_shell, true); } if (!strcmp(p, "-C")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_bool(conf, CONF_compression, true); } if (!strcmp(p, "-1")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_int(conf, CONF_sshprot, 0); /* ssh protocol 1 only */ } if (!strcmp(p, "-2")) { RETURN(1); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_int(conf, CONF_sshprot, 3); /* ssh protocol 2 only */ } if (!strcmp(p, "-i")) { Filename *fn; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); fn = filename_from_str(value); conf_set_filename(conf, CONF_keyfile, fn); filename_free(fn); } if (!strcmp(p, "-4") || !strcmp(p, "-ipv4")) { RETURN(1); SAVEABLE(1); conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV4); } if (!strcmp(p, "-6") || !strcmp(p, "-ipv6")) { RETURN(1); SAVEABLE(1); conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV6); } if (!strcmp(p, "-sercfg")) { char* nextitem; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); SAVEABLE(1); if (conf_get_int(conf, CONF_protocol) != PROT_SERIAL) cmdline_error("the -sercfg option can only be used with the " "serial protocol"); /* Value[0] contains one or more , separated values, like 19200,8,n,1,X */ nextitem = value; while (nextitem[0] != '\0') { int length, skip; char *end = strchr(nextitem, ','); if (!end) { length = strlen(nextitem); skip = 0; } else { length = end - nextitem; nextitem[length] = '\0'; skip = 1; } if (length == 1) { switch (*nextitem) { case '1': case '2': conf_set_int(conf, CONF_serstopbits, 2 * (*nextitem-'0')); break; case '5': case '6': case '7': case '8': case '9': conf_set_int(conf, CONF_serdatabits, *nextitem-'0'); break; case 'n': conf_set_int(conf, CONF_serparity, SER_PAR_NONE); break; case 'o': conf_set_int(conf, CONF_serparity, SER_PAR_ODD); break; case 'e': conf_set_int(conf, CONF_serparity, SER_PAR_EVEN); break; case 'm': conf_set_int(conf, CONF_serparity, SER_PAR_MARK); break; case 's': conf_set_int(conf, CONF_serparity, SER_PAR_SPACE); break; case 'N': conf_set_int(conf, CONF_serflow, SER_FLOW_NONE); break; case 'X': conf_set_int(conf, CONF_serflow, SER_FLOW_XONXOFF); break; case 'R': conf_set_int(conf, CONF_serflow, SER_FLOW_RTSCTS); break; case 'D': conf_set_int(conf, CONF_serflow, SER_FLOW_DSRDTR); break; default: cmdline_error("Unrecognised suboption \"-sercfg %c\"", *nextitem); } } else if (length == 3 && !strncmp(nextitem,"1.5",3)) { /* Messy special case */ conf_set_int(conf, CONF_serstopbits, 3); } else { int serspeed = atoi(nextitem); if (serspeed != 0) { conf_set_int(conf, CONF_serspeed, serspeed); } else { cmdline_error("Unrecognised suboption \"-sercfg %s\"", nextitem); } } nextitem += length + skip; } } if (!strcmp(p, "-sessionlog")) { Filename *fn; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER); /* but available even in TOOLTYPE_NONNETWORK, cf pterm "-log" */ SAVEABLE(0); fn = filename_from_str(value); conf_set_filename(conf, CONF_logfilename, fn); conf_set_int(conf, CONF_logtype, LGTYP_DEBUG); filename_free(fn); } if (!strcmp(p, "-sshlog") || !strcmp(p, "-sshrawlog")) { Filename *fn; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); fn = filename_from_str(value); conf_set_filename(conf, CONF_logfilename, fn); conf_set_int(conf, CONF_logtype, !strcmp(p, "-sshlog") ? LGTYP_PACKETS : /* !strcmp(p, "-sshrawlog") ? */ LGTYP_SSHRAW); filename_free(fn); } if (!strcmp(p, "-proxycmd")) { RETURN(2); UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(0); conf_set_int(conf, CONF_proxy_type, PROXY_CMD); conf_set_str(conf, CONF_proxy_telnet_command, value); } #ifdef _WINDOWS /* * Cross-tool options only available on Windows. */ if (!strcmp(p, "-restrict-acl") || !strcmp(p, "-restrict_acl") || !strcmp(p, "-restrictacl")) { RETURN(1); restrict_process_acl(); restricted_acl = true; } #endif return ret; /* unrecognised */ }