33#include "git2/clone.h"
44#include "git2/cred_helpers.h"
55#include "git2/sys/transport.h"
6+ #include "futils.h"
67
78#define CLONE_PATH "./foo"
89
@@ -13,36 +14,96 @@ static char *_remote_url = NULL;
1314static char * _remote_user = NULL ;
1415static char * _remote_pass = NULL ;
1516
16- static char * _remote_sslnoverify = NULL ;
1717static char * _remote_ssh_pubkey = NULL ;
1818static char * _remote_ssh_privkey = NULL ;
1919static char * _remote_ssh_passphrase = NULL ;
2020static char * _remote_ssh_fingerprint = NULL ;
2121
22+ static struct {
23+ unsigned int allowed_types ;
24+ } credentials_cb_opts ;
25+
2226static int certificate_check_cb (git_cert * cert , int valid , const char * host , void * payload )
2327{
24- GIT_UNUSED (cert );
2528 GIT_UNUSED (host );
29+ GIT_UNUSED (valid );
2630 GIT_UNUSED (payload );
2731
28- if (_remote_sslnoverify != NULL )
29- valid = 1 ;
32+ if (_remote_ssh_fingerprint && cert -> cert_type == GIT_CERT_HOSTKEY_LIBSSH2 ) {
33+ git_cert_hostkey * key = (git_cert_hostkey * ) cert ;
34+ git_oid expected ;
35+
36+ cl_git_pass (git_oid_fromstrp (& expected , _remote_ssh_fingerprint ));
37+
38+ /*
39+ * We need to figure out how long our input was to check for
40+ * the type. Here we abuse the fact that both hashes fit into
41+ * our git_oid type.
42+ */
43+ if (strlen (_remote_ssh_fingerprint ) == 32 && key -> type & GIT_CERT_SSH_MD5 ) {
44+ return (memcmp (expected .id , key -> hash_md5 , 16 ) == 0 ) ? 0 : -1 ;
45+ } else if (strlen (_remote_ssh_fingerprint ) == 40 && key -> type & GIT_CERT_SSH_SHA1 ) {
46+ return (memcmp (expected .id , key -> hash_sha1 , 20 ) == 0 ) ? 0 : -1 ;
47+ }
48+ }
49+
50+ return -1 ;
51+ }
52+
53+ static int credentials_cb (git_cred * * cred , const char * url , const char * user_from_url ,
54+ unsigned int allowed_types , void * _payload )
55+ {
56+ GIT_UNUSED (url );
57+ GIT_UNUSED (user_from_url );
58+ GIT_UNUSED (_payload );
59+
60+ if (credentials_cb_opts .allowed_types )
61+ allowed_types &= credentials_cb_opts .allowed_types ;
3062
63+ if (allowed_types & GIT_CREDTYPE_USERNAME && _remote_user )
64+ return git_cred_username_new (cred , _remote_user );
65+
66+ if (allowed_types & GIT_CREDTYPE_USERPASS_PLAINTEXT && _remote_user && _remote_pass )
67+ return git_cred_userpass_plaintext_new (cred , _remote_user , _remote_pass );
68+
69+ if (allowed_types & GIT_CREDTYPE_SSH_KEY && _remote_ssh_pubkey && _remote_ssh_privkey ) {
70+ return git_cred_ssh_key_new (cred , _remote_user , _remote_ssh_pubkey ,
71+ _remote_ssh_privkey , _remote_ssh_passphrase );
72+ }
73+
74+ if (allowed_types & GIT_CREDTYPE_SSH_MEMORY && _remote_ssh_pubkey && _remote_ssh_privkey ) {
75+ git_buf pubkey = GIT_BUF_INIT , privkey = GIT_BUF_INIT ;
76+ int error ;
77+
78+ cl_git_pass (git_futils_readbuffer (& pubkey , _remote_ssh_pubkey ));
79+ cl_git_pass (git_futils_readbuffer (& privkey , _remote_ssh_privkey ));
80+
81+ error = git_cred_ssh_key_memory_new (cred , _remote_user , pubkey .ptr ,
82+ privkey .ptr , _remote_ssh_passphrase );
83+
84+ git_buf_dispose (& pubkey );
85+ git_buf_dispose (& privkey );
86+
87+ return error ;
88+ }
3189
32- return valid ? 0 : GIT_ECERTIFICATE ;
90+ git_error_set (GIT_ERROR_NET , "unexpected cred type" );
91+ return -1 ;
3392}
3493
3594void test_online_clone_env__initialize (void )
3695{
3796 git_clone_options opts = GIT_CLONE_OPTIONS_INIT ;
3897
98+ memset (& credentials_cb_opts , 0 , sizeof (credentials_cb_opts ));
99+
39100 memcpy (& g_options , & opts , sizeof (g_options ));
40101 g_options .fetch_opts .callbacks .certificate_check = certificate_check_cb ;
102+ g_options .fetch_opts .callbacks .credentials = credentials_cb ;
41103
42104 _remote_url = cl_getenv ("GITTEST_REMOTE_URL" );
43105 _remote_user = cl_getenv ("GITTEST_REMOTE_USER" );
44106 _remote_pass = cl_getenv ("GITTEST_REMOTE_PASS" );
45- _remote_sslnoverify = cl_getenv ("GITTEST_REMOTE_SSL_NOVERIFY" );
46107 _remote_ssh_pubkey = cl_getenv ("GITTEST_REMOTE_SSH_PUBKEY" );
47108 _remote_ssh_privkey = cl_getenv ("GITTEST_REMOTE_SSH_KEY" );
48109 _remote_ssh_passphrase = cl_getenv ("GITTEST_REMOTE_SSH_PASSPHRASE" );
@@ -58,70 +119,21 @@ void test_online_clone_env__cleanup(void)
58119 git__free (_remote_url );
59120 git__free (_remote_user );
60121 git__free (_remote_pass );
61- git__free (_remote_sslnoverify );
62122 git__free (_remote_ssh_pubkey );
63123 git__free (_remote_ssh_privkey );
64124 git__free (_remote_ssh_passphrase );
65125 git__free (_remote_ssh_fingerprint );
66126}
67127
68- int cred_default (
69- git_cred * * cred ,
70- const char * url ,
71- const char * user_from_url ,
72- unsigned int allowed_types ,
73- void * payload )
128+ void test_online_clone_env__userpass_authentication (void )
74129{
75- GIT_UNUSED (url );
76- GIT_UNUSED (user_from_url );
77- GIT_UNUSED (payload );
78-
79- if (!(allowed_types & GIT_CREDTYPE_DEFAULT ))
80- return 0 ;
81-
82- return git_cred_default_new (cred );
83- }
84-
85- void test_online_clone_env__credentials (void )
86- {
87- /* Remote URL environment variable must be set.
88- * User and password are optional.
89- */
90- git_cred_userpass_payload user_pass = {
91- _remote_user ,
92- _remote_pass
93- };
94-
95130 if (!_remote_url )
96131 clar__skip ();
97132
98- if (cl_is_env_set ("GITTEST_REMOTE_DEFAULT" )) {
99- g_options .fetch_opts .callbacks .credentials = cred_default ;
100- } else {
101- g_options .fetch_opts .callbacks .credentials = git_cred_userpass ;
102- g_options .fetch_opts .callbacks .payload = & user_pass ;
103- }
104-
133+ credentials_cb_opts .allowed_types = GIT_CREDTYPE_USERPASS_PLAINTEXT |GIT_CREDTYPE_USERNAME ;
105134 cl_git_pass (git_clone (& g_repo , _remote_url , CLONE_PATH , & g_options ));
106135}
107136
108- static int cred_cb (git_cred * * cred , const char * url , const char * user_from_url ,
109- unsigned int allowed_types , void * payload )
110- {
111- GIT_UNUSED (url ); GIT_UNUSED (user_from_url ); GIT_UNUSED (payload );
112-
113- if (allowed_types & GIT_CREDTYPE_USERNAME )
114- return git_cred_username_new (cred , _remote_user );
115-
116- if (allowed_types & GIT_CREDTYPE_SSH_KEY )
117- return git_cred_ssh_key_new (cred ,
118- _remote_user , _remote_ssh_pubkey ,
119- _remote_ssh_privkey , _remote_ssh_passphrase );
120-
121- git_error_set (GIT_ERROR_NET , "unexpected cred type" );
122- return -1 ;
123- }
124-
125137static int custom_remote_ssh_with_paths (
126138 git_remote * * out ,
127139 git_repository * repo ,
@@ -155,14 +167,12 @@ void test_online_clone_env__ssh_with_paths(void)
155167 };
156168
157169#ifndef GIT_SSH
158- clar__skip ();
159- #endif
160170 if (!_remote_url || !_remote_user || strncmp (_remote_url , "ssh://" , 5 ) != 0 )
171+ #endif
161172 clar__skip ();
162173
163174 g_options .remote_cb = custom_remote_ssh_with_paths ;
164175 g_options .fetch_opts .callbacks .transport = git_transport_ssh_with_paths ;
165- g_options .fetch_opts .callbacks .credentials = cred_cb ;
166176 g_options .fetch_opts .callbacks .payload = & arr ;
167177 g_options .fetch_opts .callbacks .certificate_check = NULL ;
168178
@@ -172,105 +182,24 @@ void test_online_clone_env__ssh_with_paths(void)
172182 cl_git_pass (git_clone (& g_repo , _remote_url , CLONE_PATH , & g_options ));
173183}
174184
175- static int ssh_certificate_check (git_cert * cert , int valid , const char * host , void * payload )
176- {
177- git_cert_hostkey * key ;
178- git_oid expected = {{0 }}, actual = {{0 }};
179-
180- GIT_UNUSED (valid );
181- GIT_UNUSED (payload );
182-
183- cl_assert (_remote_ssh_fingerprint );
184-
185- cl_git_pass (git_oid_fromstrp (& expected , _remote_ssh_fingerprint ));
186- cl_assert_equal_i (GIT_CERT_HOSTKEY_LIBSSH2 , cert -> cert_type );
187- key = (git_cert_hostkey * ) cert ;
188-
189- /*
190- * We need to figure out how long our input was to check for
191- * the type. Here we abuse the fact that both hashes fit into
192- * our git_oid type.
193- */
194- if (strlen (_remote_ssh_fingerprint ) == 32 && key -> type & GIT_CERT_SSH_MD5 ) {
195- memcpy (& actual .id , key -> hash_md5 , 16 );
196- } else if (strlen (_remote_ssh_fingerprint ) == 40 && key -> type & GIT_CERT_SSH_SHA1 ) {
197- memcpy (& actual , key -> hash_sha1 , 20 );
198- } else {
199- cl_fail ("Cannot find a usable SSH hash" );
200- }
201-
202- cl_assert (!memcmp (& expected , & actual , 20 ));
203-
204- cl_assert_equal_s ("localhost" , host );
205-
206- return GIT_EUSER ;
207- }
208-
209- void test_online_clone_env__ssh_cert (void )
210- {
211- g_options .fetch_opts .callbacks .certificate_check = ssh_certificate_check ;
212-
213- if (!_remote_ssh_fingerprint )
214- cl_skip ();
215-
216- cl_git_fail_with (GIT_EUSER , git_clone (& g_repo , _remote_url , CLONE_PATH , & g_options ));
217- }
218-
219- static char * read_key_file (const char * path )
220- {
221- FILE * f ;
222- char * buf ;
223- long key_length ;
224-
225- if (!path || !* path )
226- return NULL ;
227-
228- cl_assert ((f = fopen (path , "r" )) != NULL );
229- cl_assert (fseek (f , 0 , SEEK_END ) != -1 );
230- cl_assert ((key_length = ftell (f )) != -1 );
231- cl_assert (fseek (f , 0 , SEEK_SET ) != -1 );
232- cl_assert ((buf = malloc (key_length )) != NULL );
233- cl_assert (fread (buf , key_length , 1 , f ) == 1 );
234- fclose (f );
235-
236- return buf ;
237- }
238-
239- static int ssh_memory_cred_cb (git_cred * * cred , const char * url , const char * user_from_url ,
240- unsigned int allowed_types , void * payload )
185+ void test_online_clone_env__ssh_key_authentication (void )
241186{
242- GIT_UNUSED (url ); GIT_UNUSED (user_from_url ); GIT_UNUSED (payload );
243-
244- if (allowed_types & GIT_CREDTYPE_USERNAME )
245- return git_cred_username_new (cred , _remote_user );
246-
247- if (allowed_types & GIT_CREDTYPE_SSH_KEY )
248- {
249- char * pubkey = read_key_file (_remote_ssh_pubkey );
250- char * privkey = read_key_file (_remote_ssh_privkey );
251-
252- int ret = git_cred_ssh_key_memory_new (cred , _remote_user , pubkey , privkey , _remote_ssh_passphrase );
253-
254- if (privkey )
255- free (privkey );
256- if (pubkey )
257- free (pubkey );
258- return ret ;
259- }
187+ #ifndef GIT_SSH
188+ if (!_remote_url || !_remote_user || !_remote_ssh_privkey || strncmp (_remote_url , "ssh://" , 5 ) != 0 )
189+ #endif
190+ clar__skip ();
260191
261- git_error_set ( GIT_ERROR_NET , "unexpected cred type" ) ;
262- return -1 ;
192+ credentials_cb_opts . allowed_types = GIT_CREDTYPE_SSH_KEY | GIT_CREDTYPE_USERNAME ;
193+ cl_git_pass ( git_clone ( & g_repo , _remote_url , CLONE_PATH , & g_options )) ;
263194}
264195
265- void test_online_clone_env__ssh_memory_auth (void )
196+ void test_online_clone_env__ssh_inmemory_authentication (void )
266197{
267198#ifndef GIT_SSH_MEMORY_CREDENTIALS
268- clar__skip ();
269- #endif
270199 if (!_remote_url || !_remote_user || !_remote_ssh_privkey || strncmp (_remote_url , "ssh://" , 5 ) != 0 )
200+ #endif
271201 clar__skip ();
272202
273- g_options .fetch_opts .callbacks .credentials = ssh_memory_cred_cb ;
274-
203+ credentials_cb_opts .allowed_types = GIT_CREDTYPE_SSH_MEMORY |GIT_CREDTYPE_USERNAME ;
275204 cl_git_pass (git_clone (& g_repo , _remote_url , CLONE_PATH , & g_options ));
276205}
0 commit comments