int git_openssl_stream_new(git_stream **out, const char *host, const char *port) { openssl_stream *st; st = git__calloc(1, sizeof(openssl_stream)); GITERR_CHECK_ALLOC(st); if (git_socket_stream_new((git_stream **) &st->socket, host, port)) return -1; st->ssl = SSL_new(git__ssl_ctx); if (st->ssl == NULL) { giterr_set(GITERR_SSL, "failed to create ssl object"); return -1; } st->parent.version = GIT_STREAM_VERSION; st->parent.encrypted = 1; st->parent.connect = openssl_connect; st->parent.certificate = openssl_certificate; st->parent.read = openssl_read; st->parent.write = openssl_write; st->parent.close = openssl_close; st->parent.free = openssl_free; *out = (git_stream *) st; return 0; }
int git_stransport_stream_new(git_stream **out, const char *host, const char *port) { stransport_stream *st; int error; OSStatus ret; assert(out && host); st = git__calloc(1, sizeof(stransport_stream)); GITERR_CHECK_ALLOC(st); #ifdef GIT_CURL error = git_curl_stream_new(&st->io, host, port); #else error = git_socket_stream_new(&st->io, host, port); #endif if (error < 0){ git__free(st); return error; } st->ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); if (!st->ctx) { giterr_set(GITERR_NET, "failed to create SSL context"); git__free(st); return -1; } if ((ret = SSLSetIOFuncs(st->ctx, read_cb, write_cb)) != noErr || (ret = SSLSetConnection(st->ctx, st->io)) != noErr || (ret = SSLSetSessionOption(st->ctx, kSSLSessionOptionBreakOnServerAuth, true)) != noErr || (ret = SSLSetProtocolVersionMin(st->ctx, kTLSProtocol1)) != noErr || (ret = SSLSetProtocolVersionMax(st->ctx, kTLSProtocol12)) != noErr || (ret = SSLSetPeerDomainName(st->ctx, host, strlen(host))) != noErr) { CFRelease(st->ctx); git__free(st); return stransport_error(ret); } st->parent.version = GIT_STREAM_VERSION; st->parent.encrypted = 1; st->parent.proxy_support = git_stream_supports_proxy(st->io); st->parent.connect = stransport_connect; st->parent.certificate = stransport_certificate; st->parent.set_proxy = stransport_set_proxy; st->parent.read = stransport_read; st->parent.write = stransport_write; st->parent.close = stransport_close; st->parent.free = stransport_free; *out = (git_stream *) st; return 0; }
int git_openssl_stream_new(git_stream **out, const char *host, const char *port) { int error; openssl_stream *st; st = git__calloc(1, sizeof(openssl_stream)); GITERR_CHECK_ALLOC(st); st->io = NULL; #ifdef GIT_CURL error = git_curl_stream_new(&st->io, host, port); #else error = git_socket_stream_new(&st->io, host, port); #endif if (error < 0) goto out_err; st->ssl = SSL_new(git__ssl_ctx); if (st->ssl == NULL) { giterr_set(GITERR_SSL, "failed to create ssl object"); error = -1; goto out_err; } st->host = git__strdup(host); GITERR_CHECK_ALLOC(st->host); st->parent.version = GIT_STREAM_VERSION; st->parent.encrypted = 1; st->parent.proxy_support = git_stream_supports_proxy(st->io); st->parent.connect = openssl_connect; st->parent.certificate = openssl_certificate; st->parent.set_proxy = openssl_set_proxy; st->parent.read = openssl_read; st->parent.write = openssl_write; st->parent.close = openssl_close; st->parent.free = openssl_free; *out = (git_stream *) st; return 0; out_err: git_stream_free(st->io); git__free(st); return error; }
static int git_proto_stream_alloc( git_subtransport *t, const char *url, const char *cmd, const char *host, const char *port, git_smart_subtransport_stream **stream) { git_proto_stream *s; if (!stream) return -1; s = git__calloc(1, sizeof(git_proto_stream)); GIT_ERROR_CHECK_ALLOC(s); s->parent.subtransport = &t->parent; s->parent.read = git_proto_stream_read; s->parent.write = git_proto_stream_write; s->parent.free = git_proto_stream_free; s->cmd = cmd; s->url = git__strdup(url); if (!s->url) { git__free(s); return -1; } if ((git_socket_stream_new(&s->io, host, port)) < 0) return -1; GIT_ERROR_CHECK_VERSION(s->io, GIT_STREAM_VERSION, "git_stream"); *stream = &s->parent; return 0; }
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; }