static int _git_ssh_setup_conn( ssh_subtransport *t, const char *url, const char *cmd, git_smart_subtransport_stream **stream) { char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; int auth_methods, error = 0; size_t i; ssh_stream *s; git_cred *cred = NULL; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; t->current_stream = NULL; *stream = NULL; if (ssh_stream_alloc(t, url, cmd, stream) < 0) return -1; s = (ssh_stream *)*stream; s->session = NULL; s->channel = NULL; for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) { const char *p = ssh_prefixes[i]; if (!git__prefixcmp(url, p)) { if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0) goto done; goto post_extract; } } if ((error = git_ssh_extract_url_parts(&host, &user, url)) < 0) goto done; port = git__strdup(default_port); GITERR_CHECK_ALLOC(port); post_extract: if ((error = git_socket_stream_new(&s->io, host, port)) < 0 || (error = git_stream_connect(s->io)) < 0) goto done; if ((error = _git_ssh_session_create(&session, s->io)) < 0) goto done; if (t->owner->certificate_check_cb != NULL) { git_cert_hostkey cert = {{ 0 }}, *cert_ptr; const char *key; cert.parent.cert_type = GIT_CERT_HOSTKEY_LIBSSH2; key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); if (key != NULL) { cert.type |= GIT_CERT_SSH_SHA1; memcpy(&cert.hash_sha1, key, 20); } key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); if (key != NULL) { cert.type |= GIT_CERT_SSH_MD5; memcpy(&cert.hash_md5, key, 16); } if (cert.type == 0) { giterr_set(GITERR_SSH, "unable to get the host key"); error = -1; goto done; } /* We don't currently trust any hostkeys */ giterr_clear(); cert_ptr = &cert; error = t->owner->certificate_check_cb((git_cert *) cert_ptr, 0, host, t->owner->message_cb_payload); if (error < 0) { if (!giterr_last()) giterr_set(GITERR_NET, "user cancelled hostkey check"); goto done; } } /* we need the username to ask for auth methods */ if (!user) { if ((error = request_creds(&cred, t, NULL, GIT_CREDTYPE_USERNAME)) < 0) goto done; user = git__strdup(((git_cred_username *) cred)->username); cred->free(cred); cred = NULL; if (!user) goto done; } else if (user && pass) { if ((error = git_cred_userpass_plaintext_new(&cred, user, pass)) < 0) goto done; } if ((error = list_auth_methods(&auth_methods, session, user)) < 0) goto done; error = GIT_EAUTH; /* if we already have something to try */ if (cred && auth_methods & cred->credtype) error = _git_ssh_authenticate_session(session, cred); while (error == GIT_EAUTH) { if (cred) { cred->free(cred); cred = NULL; } if ((error = request_creds(&cred, t, user, auth_methods)) < 0) goto done; if (strcmp(user, git_cred__username(cred))) { giterr_set(GITERR_SSH, "username does not match previous request"); error = -1; goto done; } error = _git_ssh_authenticate_session(session, cred); } if (error < 0) goto done; channel = libssh2_channel_open_session(session); if (!channel) { error = -1; ssh_error(session, "Failed to open SSH channel"); goto done; } libssh2_channel_set_blocking(channel, 1); s->session = session; s->channel = channel; t->current_stream = s; done: if (error < 0) { ssh_stream_free(*stream); if (session) libssh2_session_free(session); } if (cred) cred->free(cred); git__free(host); git__free(port); git__free(path); git__free(user); git__free(pass); return error; }
static int _git_ssh_setup_conn( ssh_subtransport *t, const char *url, const char *cmd, git_smart_subtransport_stream **stream) { char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; ssh_stream *s; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; *stream = NULL; if (ssh_stream_alloc(t, url, cmd, stream) < 0) return -1; s = (ssh_stream *)*stream; if (!git__prefixcmp(url, prefix_ssh)) { if (gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port) < 0) goto on_error; } else { if (git_ssh_extract_url_parts(&host, &user, url) < 0) goto on_error; port = git__strdup(default_port); GITERR_CHECK_ALLOC(port); } if (gitno_connect(&s->socket, host, port, 0) < 0) goto on_error; if (user && pass) { if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0) goto on_error; } else if (t->owner->cred_acquire_cb) { if (t->owner->cred_acquire_cb( &t->cred, t->owner->url, user, GIT_CREDTYPE_USERPASS_PLAINTEXT | GIT_CREDTYPE_SSH_KEY | GIT_CREDTYPE_SSH_CUSTOM, t->owner->cred_acquire_payload) < 0) goto on_error; if (!t->cred) { giterr_set(GITERR_SSH, "Callback failed to initialize SSH credentials"); goto on_error; } } else { giterr_set(GITERR_SSH, "Cannot set up SSH connection without credentials"); goto on_error; } assert(t->cred); if (!user && !git_cred_has_username(t->cred)) { giterr_set_str(GITERR_NET, "Cannot authenticate without a username"); goto on_error; } if (_git_ssh_session_create(&session, s->socket) < 0) goto on_error; if (_git_ssh_authenticate_session(session, user, t->cred) < 0) goto on_error; channel = libssh2_channel_open_session(session); if (!channel) { ssh_error(session, "Failed to open SSH channel"); goto on_error; } libssh2_channel_set_blocking(channel, 1); s->session = session; s->channel = channel; t->current_stream = s; git__free(host); git__free(port); git__free(path); git__free(user); git__free(pass); return 0; on_error: s->session = NULL; s->channel = NULL; t->current_stream = NULL; if (*stream) ssh_stream_free(*stream); git__free(host); git__free(port); git__free(user); git__free(pass); if (session) libssh2_session_free(session); return -1; }
static int _git_ssh_setup_tunnel( ssh_subtransport *t, const char *url, const char *gitCmd, git_smart_subtransport_stream **stream) { char *host = NULL, *port = NULL, *path = NULL, *user = NULL, *pass = NULL; size_t i; ssh_stream *s; wchar_t *ssh = t->sshtoolpath; wchar_t *wideParams = NULL; wchar_t *cmd = NULL; git_buf params = GIT_BUF_INIT; int isPutty; size_t length; *stream = NULL; if (ssh_stream_alloc(t, url, gitCmd, stream) < 0) { giterr_set_oom(); return -1; } s = (ssh_stream *)*stream; for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) { const char *p = ssh_prefixes[i]; if (!git__prefixcmp(url, p)) { if (extract_url_parts(&host, &port, &path, &user, &pass, url, NULL) < 0) goto on_error; goto post_extract; } } if (git_ssh_extract_url_parts(&host, &user, url) < 0) goto on_error; post_extract: if (!ssh) { giterr_set(GITERR_SSH, "No GIT_SSH tool configured"); goto on_error; } isPutty = wcstristr(ssh, L"plink"); if (port) { if (isPutty) git_buf_printf(¶ms, " -P %s", port); else git_buf_printf(¶ms, " -p %s", port); } if (isPutty && !wcstristr(ssh, L"tortoiseplink")) { git_buf_puts(¶ms, " -batch"); } if (user) git_buf_printf(¶ms, " %s@%s ", user, host); else git_buf_printf(¶ms, " %s ", host); if (gen_proto(¶ms, s->cmd, s->url)) goto on_error; if (git_buf_oom(¶ms)) { giterr_set_oom(); goto on_error; } if (git__utf8_to_16_alloc(&wideParams, params.ptr) < 0) { giterr_set_oom(); goto on_error; } git_buf_free(¶ms); length = wcslen(ssh) + wcslen(wideParams) + 3; cmd = git__calloc(length, sizeof(wchar_t)); if (!cmd) { giterr_set_oom(); goto on_error; } wcscat_s(cmd, length, L"\""); wcscat_s(cmd, length, ssh); wcscat_s(cmd, length, L"\""); wcscat_s(cmd, length, wideParams); if (command_start(cmd, &s->commandHandle, t->pEnv, isPutty ? CREATE_NEW_CONSOLE : DETACHED_PROCESS)) goto on_error; git__free(wideParams); git__free(cmd); t->current_stream = s; git__free(host); git__free(port); git__free(path); git__free(user); git__free(pass); return 0; on_error: t->current_stream = NULL; if (*stream) ssh_stream_free(*stream); git_buf_free(¶ms); if (wideParams) git__free(wideParams); if (cmd) git__free(cmd); git__free(host); git__free(port); git__free(user); git__free(pass); return -1; }
static int _git_ssh_setup_conn( ssh_subtransport *t, const char *url, const char *cmd, git_smart_subtransport_stream **stream) { char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; int auth_methods, error = 0; ssh_stream *s; git_cred *cred = NULL; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; *stream = NULL; if (ssh_stream_alloc(t, url, cmd, stream) < 0) return -1; s = (ssh_stream *)*stream; if (!git__prefixcmp(url, prefix_ssh)) { if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0) goto on_error; } else { if ((error = git_ssh_extract_url_parts(&host, &user, url)) < 0) goto on_error; port = git__strdup(default_port); GITERR_CHECK_ALLOC(port); } /* we need the username to ask for auth methods */ if (!user) { if ((error = request_creds(&cred, t, NULL, GIT_CREDTYPE_USERNAME)) < 0) goto on_error; user = git__strdup(((git_cred_username *) cred)->username); cred->free(cred); cred = NULL; if (!user) goto on_error; } else if (user && pass) { if ((error = git_cred_userpass_plaintext_new(&cred, user, pass)) < 0) goto on_error; } if ((error = gitno_connect(&s->socket, host, port, 0)) < 0) goto on_error; if ((error = _git_ssh_session_create(&session, s->socket)) < 0) goto on_error; if ((error = list_auth_methods(&auth_methods, session, user)) < 0) goto on_error; error = GIT_EAUTH; /* if we already have something to try */ if (cred && auth_methods & cred->credtype) error = _git_ssh_authenticate_session(session, cred); while (error == GIT_EAUTH) { if (cred) { cred->free(cred); cred = NULL; } if ((error = request_creds(&cred, t, user, auth_methods)) < 0) goto on_error; if (strcmp(user, git_cred__username(cred))) { giterr_set(GITERR_SSH, "username does not match previous request"); error = -1; goto on_error; } error = _git_ssh_authenticate_session(session, cred); } if (error < 0) goto on_error; channel = libssh2_channel_open_session(session); if (!channel) { error = -1; ssh_error(session, "Failed to open SSH channel"); goto on_error; } libssh2_channel_set_blocking(channel, 1); s->session = session; s->channel = channel; t->current_stream = s; if (cred) cred->free(cred); git__free(host); git__free(port); git__free(path); git__free(user); git__free(pass); return 0; on_error: s->session = NULL; s->channel = NULL; t->current_stream = NULL; if (*stream) ssh_stream_free(*stream); if (cred) cred->free(cred); git__free(host); git__free(port); git__free(user); git__free(pass); if (session) libssh2_session_free(session); return error; }
static int _git_ssh_setup_conn( ssh_subtransport *t, const char *url, const char *cmd, git_smart_subtransport_stream **stream ) { char *host, *port=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; ssh_stream *s; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; *stream = NULL; if (ssh_stream_alloc(t, url, cmd, stream) < 0) return -1; s = (ssh_stream *)*stream; if (!git__prefixcmp(url, prefix_ssh)) { url = url + strlen(prefix_ssh); if (gitno_extract_url_parts(&host, &port, &user, &pass, url, default_port) < 0) goto on_error; } else { if (git_ssh_extract_url_parts(&host, &user, url) < 0) goto on_error; port = git__strdup(default_port); GITERR_CHECK_ALLOC(port); } if (gitno_connect(&s->socket, host, port, 0) < 0) goto on_error; if (user && pass) { if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0) goto on_error; } else { if (t->owner->cred_acquire_cb(&t->cred, t->owner->url, user, GIT_CREDTYPE_USERPASS_PLAINTEXT | GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE | GIT_CREDTYPE_SSH_PUBLICKEY, t->owner->cred_acquire_payload) < 0) return -1; } assert(t->cred); if (!user) { user = git__strdup(default_user); } if (_git_ssh_session_create(&session, s->socket) < 0) goto on_error; if (_git_ssh_authenticate_session(session, user, t->cred) < 0) goto on_error; channel = libssh2_channel_open_session(session); if (!channel) goto on_error; libssh2_channel_set_blocking(channel, 1); s->session = session; s->channel = channel; t->current_stream = s; git__free(host); git__free(port); git__free(user); git__free(pass); return 0; on_error: if (*stream) ssh_stream_free(*stream); git__free(host); git__free(port); git__free(user); git__free(pass); if (session) libssh2_session_free(session), session = NULL; return -1; }