📄 sshconnect2.c
字号:
} return private;}/* * try keys in the following order: * 1. agent keys that are found in the config file * 2. other agent keys * 3. keys that are only listed in the config file */static voidpubkey_prepare(Authctxt *authctxt){ Identity *id; Idlist agent, files, *preferred; Key *key; AuthenticationConnection *ac; char *comment; int i, found; TAILQ_INIT(&agent); /* keys from the agent */ TAILQ_INIT(&files); /* keys from the config file */ preferred = &authctxt->keys; TAILQ_INIT(preferred); /* preferred order of keys */ /* list of keys stored in the filesystem */ for (i = 0; i < options.num_identity_files; i++) { key = options.identity_keys[i]; if (key && key->type == KEY_RSA1) continue; options.identity_keys[i] = NULL; id = xmalloc(sizeof(*id)); memset(id, 0, sizeof(*id)); id->key = key; id->filename = xstrdup(options.identity_files[i]); TAILQ_INSERT_TAIL(&files, id, next); } /* list of keys supported by the agent */ if ((ac = ssh_get_authentication_connection())) { for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2)) { found = 0; TAILQ_FOREACH(id, &files, next) { /* agent keys from the config file are preferred */ if (key_equal(key, id->key)) { key_free(key); xfree(comment); TAILQ_REMOVE(&files, id, next); TAILQ_INSERT_TAIL(preferred, id, next); id->ac = ac; found = 1; break; } } if (!found && !options.identities_only) { id = xmalloc(sizeof(*id)); memset(id, 0, sizeof(*id)); id->key = key; id->filename = comment; id->ac = ac; TAILQ_INSERT_TAIL(&agent, id, next); } } /* append remaining agent keys */ for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) { TAILQ_REMOVE(&agent, id, next); TAILQ_INSERT_TAIL(preferred, id, next); } authctxt->agent = ac; } /* append remaining keys from the config file */ for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) { TAILQ_REMOVE(&files, id, next); TAILQ_INSERT_TAIL(preferred, id, next); } TAILQ_FOREACH(id, preferred, next) { debug2("key: %s (%p)", id->filename, id->key); }}static voidpubkey_cleanup(Authctxt *authctxt){ Identity *id; if (authctxt->agent != NULL) ssh_close_authentication_connection(authctxt->agent); for (id = TAILQ_FIRST(&authctxt->keys); id; id = TAILQ_FIRST(&authctxt->keys)) { TAILQ_REMOVE(&authctxt->keys, id, next); if (id->key) key_free(id->key); if (id->filename) xfree(id->filename); xfree(id); }}intuserauth_pubkey(Authctxt *authctxt){ Identity *id; int sent = 0; while ((id = TAILQ_FIRST(&authctxt->keys))) { if (id->tried++) return (0); /* move key to the end of the queue */ TAILQ_REMOVE(&authctxt->keys, id, next); TAILQ_INSERT_TAIL(&authctxt->keys, id, next); /* * send a test message if we have the public key. for * encrypted keys we cannot do this and have to load the * private key instead */ if (id->key && id->key->type != KEY_RSA1) { debug("Offering public key: %s", id->filename); sent = send_pubkey_test(authctxt, id); } else if (id->key == NULL) { debug("Trying private key: %s", id->filename); id->key = load_identity_file(id->filename); if (id->key != NULL) { id->isprivate = 1; sent = sign_and_send_pubkey(authctxt, id); key_free(id->key); id->key = NULL; } } if (sent) return (sent); } return (0);}/* * Send userauth request message specifying keyboard-interactive method. */intuserauth_kbdint(Authctxt *authctxt){ static int attempt = 0; if (attempt++ >= options.number_of_password_prompts) return 0; /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */ if (attempt > 1 && !authctxt->info_req_seen) { debug3("userauth_kbdint: disable: no info_req_seen"); dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL); return 0; } debug2("userauth_kbdint"); packet_start(SSH2_MSG_USERAUTH_REQUEST); packet_put_cstring(authctxt->server_user); packet_put_cstring(authctxt->service); packet_put_cstring(authctxt->method->name); packet_put_cstring(""); /* lang */ packet_put_cstring(options.kbd_interactive_devices ? options.kbd_interactive_devices : ""); packet_send(); dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req); return 1;}/* * parse INFO_REQUEST, prompt user and send INFO_RESPONSE */voidinput_userauth_info_req(int type, u_int32_t seq, void *ctxt){ Authctxt *authctxt = ctxt; char *name, *inst, *lang, *prompt, *response; u_int num_prompts, i; int echo = 0; debug2("input_userauth_info_req"); if (authctxt == NULL) fatal("input_userauth_info_req: no authentication context"); authctxt->info_req_seen = 1; name = packet_get_string(NULL); inst = packet_get_string(NULL); lang = packet_get_string(NULL); if (strlen(name) > 0) logit("%s", name); if (strlen(inst) > 0) logit("%s", inst); xfree(name); xfree(inst); xfree(lang); num_prompts = packet_get_int(); /* * Begin to build info response packet based on prompts requested. * We commit to providing the correct number of responses, so if * further on we run into a problem that prevents this, we have to * be sure and clean this up and send a correct error response. */ packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE); packet_put_int(num_prompts); debug2("input_userauth_info_req: num_prompts %d", num_prompts); for (i = 0; i < num_prompts; i++) { prompt = packet_get_string(NULL); echo = packet_get_char(); response = read_passphrase(prompt, echo ? RP_ECHO : 0); packet_put_cstring(response); memset(response, 0, strlen(response)); xfree(response); xfree(prompt); } packet_check_eom(); /* done with parsing incoming message. */ packet_add_padding(64); packet_send();}static intssh_keysign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen){ Buffer b; struct stat st; pid_t pid; int to[2], from[2], status, version = 2; debug2("ssh_keysign called"); if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) { error("ssh_keysign: no installed: %s", strerror(errno)); return -1; } if (fflush(stdout) != 0) error("ssh_keysign: fflush: %s", strerror(errno)); if (pipe(to) < 0) { error("ssh_keysign: pipe: %s", strerror(errno)); return -1; } if (pipe(from) < 0) { error("ssh_keysign: pipe: %s", strerror(errno)); return -1; } if ((pid = fork()) < 0) { error("ssh_keysign: fork: %s", strerror(errno)); return -1; } if (pid == 0) { seteuid(getuid()); setuid(getuid()); close(from[0]); if (dup2(from[1], STDOUT_FILENO) < 0) fatal("ssh_keysign: dup2: %s", strerror(errno)); close(to[1]); if (dup2(to[0], STDIN_FILENO) < 0) fatal("ssh_keysign: dup2: %s", strerror(errno)); close(from[1]); close(to[0]); execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0); fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN, strerror(errno)); } close(from[1]); close(to[0]); buffer_init(&b); buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */ buffer_put_string(&b, data, datalen); if (ssh_msg_send(to[1], version, &b) == -1) fatal("ssh_keysign: couldn't send request"); if (ssh_msg_recv(from[0], &b) < 0) { error("ssh_keysign: no reply"); buffer_free(&b); return -1; } close(from[0]); close(to[1]); while (waitpid(pid, &status, 0) < 0) if (errno != EINTR) break; if (buffer_get_char(&b) != version) { error("ssh_keysign: bad version"); buffer_free(&b); return -1; } *sigp = buffer_get_string(&b, lenp); buffer_free(&b); return 0;}intuserauth_hostbased(Authctxt *authctxt){ Key *private = NULL; Sensitive *sensitive = authctxt->sensitive; Buffer b; u_char *signature, *blob; char *chost, *pkalg, *p; const char *service; u_int blen, slen; int ok, i, len, found = 0; /* check for a useful key */ for (i = 0; i < sensitive->nkeys; i++) { private = sensitive->keys[i]; if (private && private->type != KEY_RSA1) { found = 1; /* we take and free the key */ sensitive->keys[i] = NULL; break; } } if (!found) { debug("No more client hostkeys for hostbased authentication."); return 0; } if (key_to_blob(private, &blob, &blen) == 0) { key_free(private); return 0; } /* figure out a name for the client host */ p = get_local_name(packet_get_connection_in()); if (p == NULL) { error("userauth_hostbased: cannot get local ipaddr/name"); key_free(private); return 0; } len = strlen(p) + 2; chost = xmalloc(len); strlcpy(chost, p, len); strlcat(chost, ".", len); debug2("userauth_hostbased: chost %s", chost); xfree(p); service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : authctxt->service; pkalg = xstrdup(key_ssh_name(private)); buffer_init(&b); /* construct data */ buffer_put_string(&b, session_id2, session_id2_len); buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); buffer_put_cstring(&b, authctxt->server_user); buffer_put_cstring(&b, service); buffer_put_cstring(&b, authctxt->method->name); buffer_put_cstring(&b, pkalg); buffer_put_string(&b, blob, blen); buffer_put_cstring(&b, chost); buffer_put_cstring(&b, authctxt->local_user);#ifdef DEBUG_PK buffer_dump(&b);#endif if (sensitive->external_keysign) ok = ssh_keysign(private, &signature, &slen, buffer_ptr(&b), buffer_len(&b)); else ok = key_sign(private, &signature, &slen, buffer_ptr(&b), buffer_len(&b)); key_free(private); buffer_free(&b); if (ok != 0) { error("key_sign failed"); xfree(chost); xfree(pkalg); return 0; } packet_start(SSH2_MSG_USERAUTH_REQUEST); packet_put_cstring(authctxt->server_user); packet_put_cstring(authctxt->service); packet_put_cstring(authctxt->method->name); packet_put_cstring(pkalg); packet_put_string(blob, blen); packet_put_cstring(chost); packet_put_cstring(authctxt->local_user); packet_put_string(signature, slen); memset(signature, 's', slen); xfree(signature); xfree(chost); xfree(pkalg); packet_send(); return 1;}/* find auth method *//* * given auth method name, if configurable options permit this method fill * in auth_ident field and return true, otherwise return false. */static intauthmethod_is_enabled(Authmethod *method){ if (method == NULL) return 0; /* return false if options indicate this method is disabled */ if (method->enabled == NULL || *method->enabled == 0) return 0; /* return false if batch mode is enabled but method needs interactive mode */ if (method->batch_flag != NULL && *method->batch_flag != 0) return 0; return 1;}static Authmethod *authmethod_lookup(const char *name){ Authmethod *method = NULL; if (name != NULL) for (method = authmethods; method->name != NULL; method++) if (strcmp(name, method->name) == 0) return method; debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); return NULL;}/* XXX internal state */static Authmethod *current = NULL;static char *supported = NULL;static char *preferred = NULL;/* * Given the authentication method list sent by the server, return the * next method we should try. If the server initially sends a nil list, * use a built-in default list. */static Authmethod *authmethod_get(char *authlist){ char *name = NULL; u_int next; /* Use a suitable default if we're passed a nil list. */ if (authlist == NULL || strlen(authlist) == 0) authlist = options.preferred_authentications; if (supported == NULL || strcmp(authlist, supported) != 0) { debug3("start over, passed a different list %s", authlist); if (supported != NULL) xfree(supported); supported = xstrdup(authlist); preferred = options.preferred_authentications; debug3("preferred %s", preferred); current = NULL; } else if (current != NULL && authmethod_is_enabled(current)) return current; for (;;) { if ((name = match_list(preferred, supported, &next)) == NULL) { debug("No more authentication methods to try."); current = NULL; return NULL; } preferred += next; debug3("authmethod_lookup %s", name); debug3("remaining preferred: %s", preferred); if ((current = authmethod_lookup(name)) != NULL && authmethod_is_enabled(current)) { debug3("authmethod_is_enabled %s", name); debug("Next authentication method: %s", name); return current; } }}static char *authmethods_get(void){ Authmethod *method = NULL; Buffer b; char *list; buffer_init(&b); for (method = authmethods; method->name != NULL; method++) { if (authmethod_is_enabled(method)) { if (buffer_len(&b) > 0) buffer_append(&b, ",", 1); buffer_append(&b, method->name, strlen(method->name)); } } buffer_append(&b, "\0", 1); list = xstrdup(buffer_ptr(&b)); buffer_free(&b); return list;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -