1 /*
2  * Copyright (C) the libgit2 contributors. All rights reserved.
3  *
4  * This file is part of libgit2, distributed under the GNU GPL v2 with
5  * a Linking Exception. For full terms see the included COPYING file.
6  */
7 
8 #include "common.h"
9 
10 #ifdef GIT_OPENSSL
11 # include <openssl/err.h>
12 #endif
13 
14 #ifdef GIT_MBEDTLS
15 # include <mbedtls/error.h>
16 #endif
17 
18 #include <git2.h>
19 #include "alloc.h"
20 #include "sysdir.h"
21 #include "cache.h"
22 #include "global.h"
23 #include "object.h"
24 #include "odb.h"
25 #include "refs.h"
26 #include "index.h"
27 #include "transports/smart.h"
28 #include "transports/http.h"
29 #include "streams/openssl.h"
30 #include "streams/mbedtls.h"
31 
git_libgit2_version(int * major,int * minor,int * rev)32 int git_libgit2_version(int *major, int *minor, int *rev)
33 {
34 	*major = LIBGIT2_VER_MAJOR;
35 	*minor = LIBGIT2_VER_MINOR;
36 	*rev = LIBGIT2_VER_REVISION;
37 
38 	return 0;
39 }
40 
git_libgit2_features(void)41 int git_libgit2_features(void)
42 {
43 	return 0
44 #ifdef GIT_THREADS
45 		| GIT_FEATURE_THREADS
46 #endif
47 #ifdef GIT_HTTPS
48 		| GIT_FEATURE_HTTPS
49 #endif
50 #if defined(GIT_SSH)
51 		| GIT_FEATURE_SSH
52 #endif
53 #if defined(GIT_USE_NSEC)
54 		| GIT_FEATURE_NSEC
55 #endif
56 	;
57 }
58 
59 /* Declarations for tuneable settings */
60 extern size_t git_mwindow__window_size;
61 extern size_t git_mwindow__mapped_limit;
62 extern size_t git_mwindow__file_limit;
63 extern size_t git_indexer__max_objects;
64 extern bool git_disable_pack_keep_file_checks;
65 
config_level_to_sysdir(int config_level)66 static int config_level_to_sysdir(int config_level)
67 {
68 	int val = -1;
69 
70 	switch (config_level) {
71 	case GIT_CONFIG_LEVEL_SYSTEM:
72 		val = GIT_SYSDIR_SYSTEM;
73 		break;
74 	case GIT_CONFIG_LEVEL_XDG:
75 		val = GIT_SYSDIR_XDG;
76 		break;
77 	case GIT_CONFIG_LEVEL_GLOBAL:
78 		val = GIT_SYSDIR_GLOBAL;
79 		break;
80 	case GIT_CONFIG_LEVEL_PROGRAMDATA:
81 		val = GIT_SYSDIR_PROGRAMDATA;
82 		break;
83 	default:
84 		git_error_set(
85 			GIT_ERROR_INVALID, "invalid config path selector %d", config_level);
86 	}
87 
88 	return val;
89 }
90 
91 extern char *git__user_agent;
92 extern char *git__ssl_ciphers;
93 
git_libgit2__user_agent(void)94 const char *git_libgit2__user_agent(void)
95 {
96 	return git__user_agent;
97 }
98 
git_libgit2__ssl_ciphers(void)99 const char *git_libgit2__ssl_ciphers(void)
100 {
101 	return git__ssl_ciphers;
102 }
103 
git_libgit2_opts(int key,...)104 int git_libgit2_opts(int key, ...)
105 {
106 	int error = 0;
107 	va_list ap;
108 
109 	va_start(ap, key);
110 
111 	switch (key) {
112 	case GIT_OPT_SET_MWINDOW_SIZE:
113 		git_mwindow__window_size = va_arg(ap, size_t);
114 		break;
115 
116 	case GIT_OPT_GET_MWINDOW_SIZE:
117 		*(va_arg(ap, size_t *)) = git_mwindow__window_size;
118 		break;
119 
120 	case GIT_OPT_SET_MWINDOW_MAPPED_LIMIT:
121 		git_mwindow__mapped_limit = va_arg(ap, size_t);
122 		break;
123 
124 	case GIT_OPT_GET_MWINDOW_MAPPED_LIMIT:
125 		*(va_arg(ap, size_t *)) = git_mwindow__mapped_limit;
126 		break;
127 
128 	case GIT_OPT_SET_MWINDOW_FILE_LIMIT:
129 		git_mwindow__file_limit = va_arg(ap, size_t);
130 		break;
131 
132 	case GIT_OPT_GET_MWINDOW_FILE_LIMIT:
133 		*(va_arg(ap, size_t *)) = git_mwindow__file_limit;
134 		break;
135 
136 	case GIT_OPT_GET_SEARCH_PATH:
137 		if ((error = config_level_to_sysdir(va_arg(ap, int))) >= 0) {
138 			git_buf *out = va_arg(ap, git_buf *);
139 			const git_buf *tmp;
140 
141 			git_buf_sanitize(out);
142 			if ((error = git_sysdir_get(&tmp, error)) < 0)
143 				break;
144 
145 			error = git_buf_sets(out, tmp->ptr);
146 		}
147 		break;
148 
149 	case GIT_OPT_SET_SEARCH_PATH:
150 		if ((error = config_level_to_sysdir(va_arg(ap, int))) >= 0)
151 			error = git_sysdir_set(error, va_arg(ap, const char *));
152 		break;
153 
154 	case GIT_OPT_SET_CACHE_OBJECT_LIMIT:
155 		{
156 			git_object_t type = (git_object_t)va_arg(ap, int);
157 			size_t size = va_arg(ap, size_t);
158 			error = git_cache_set_max_object_size(type, size);
159 			break;
160 		}
161 
162 	case GIT_OPT_SET_CACHE_MAX_SIZE:
163 		git_cache__max_storage = va_arg(ap, ssize_t);
164 		break;
165 
166 	case GIT_OPT_ENABLE_CACHING:
167 		git_cache__enabled = (va_arg(ap, int) != 0);
168 		break;
169 
170 	case GIT_OPT_GET_CACHED_MEMORY:
171 		*(va_arg(ap, ssize_t *)) = git_cache__current_storage.val;
172 		*(va_arg(ap, ssize_t *)) = git_cache__max_storage;
173 		break;
174 
175 	case GIT_OPT_GET_TEMPLATE_PATH:
176 		{
177 			git_buf *out = va_arg(ap, git_buf *);
178 			const git_buf *tmp;
179 
180 			git_buf_sanitize(out);
181 			if ((error = git_sysdir_get(&tmp, GIT_SYSDIR_TEMPLATE)) < 0)
182 				break;
183 
184 			error = git_buf_sets(out, tmp->ptr);
185 		}
186 		break;
187 
188 	case GIT_OPT_SET_TEMPLATE_PATH:
189 		error = git_sysdir_set(GIT_SYSDIR_TEMPLATE, va_arg(ap, const char *));
190 		break;
191 
192 	case GIT_OPT_SET_SSL_CERT_LOCATIONS:
193 #ifdef GIT_OPENSSL
194 		{
195 			const char *file = va_arg(ap, const char *);
196 			const char *path = va_arg(ap, const char *);
197 			error = git_openssl__set_cert_location(file, path);
198 		}
199 #elif defined(GIT_MBEDTLS)
200 		{
201 			const char *file = va_arg(ap, const char *);
202 			const char *path = va_arg(ap, const char *);
203 			if (file)
204 				error = git_mbedtls__set_cert_location(file, 0);
205 			if (error && path)
206 				error = git_mbedtls__set_cert_location(path, 1);
207 		}
208 #else
209 		git_error_set(GIT_ERROR_SSL, "TLS backend doesn't support certificate locations");
210 		error = -1;
211 #endif
212 		break;
213 	case GIT_OPT_SET_USER_AGENT:
214 		git__free(git__user_agent);
215 		git__user_agent = git__strdup(va_arg(ap, const char *));
216 		if (!git__user_agent) {
217 			git_error_set_oom();
218 			error = -1;
219 		}
220 
221 		break;
222 
223 	case GIT_OPT_ENABLE_STRICT_OBJECT_CREATION:
224 		git_object__strict_input_validation = (va_arg(ap, int) != 0);
225 		break;
226 
227 	case GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION:
228 		git_reference__enable_symbolic_ref_target_validation = (va_arg(ap, int) != 0);
229 		break;
230 
231 	case GIT_OPT_SET_SSL_CIPHERS:
232 #if (GIT_OPENSSL || GIT_MBEDTLS)
233 		{
234 			git__free(git__ssl_ciphers);
235 			git__ssl_ciphers = git__strdup(va_arg(ap, const char *));
236 			if (!git__ssl_ciphers) {
237 				git_error_set_oom();
238 				error = -1;
239 			}
240 		}
241 #else
242 		git_error_set(GIT_ERROR_SSL, "TLS backend doesn't support custom ciphers");
243 		error = -1;
244 #endif
245 		break;
246 
247 	case GIT_OPT_GET_USER_AGENT:
248 		{
249 			git_buf *out = va_arg(ap, git_buf *);
250 			git_buf_sanitize(out);
251 			error = git_buf_sets(out, git__user_agent);
252 		}
253 		break;
254 
255 	case GIT_OPT_ENABLE_OFS_DELTA:
256 		git_smart__ofs_delta_enabled = (va_arg(ap, int) != 0);
257 		break;
258 
259 	case GIT_OPT_ENABLE_FSYNC_GITDIR:
260 		git_repository__fsync_gitdir = (va_arg(ap, int) != 0);
261 		break;
262 
263 	case GIT_OPT_GET_WINDOWS_SHAREMODE:
264 #ifdef GIT_WIN32
265 		*(va_arg(ap, unsigned long *)) = git_win32__createfile_sharemode;
266 #endif
267 		break;
268 
269 	case GIT_OPT_SET_WINDOWS_SHAREMODE:
270 #ifdef GIT_WIN32
271 		git_win32__createfile_sharemode = va_arg(ap, unsigned long);
272 #endif
273 		break;
274 
275 	case GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION:
276 		git_odb__strict_hash_verification = (va_arg(ap, int) != 0);
277 		break;
278 
279 	case GIT_OPT_SET_ALLOCATOR:
280 		error = git_allocator_setup(va_arg(ap, git_allocator *));
281 		break;
282 
283 	case GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY:
284 		git_index__enforce_unsaved_safety = (va_arg(ap, int) != 0);
285 		break;
286 
287 	case GIT_OPT_SET_PACK_MAX_OBJECTS:
288 		git_indexer__max_objects = va_arg(ap, size_t);
289 		break;
290 
291 	case GIT_OPT_GET_PACK_MAX_OBJECTS:
292 		*(va_arg(ap, size_t *)) = git_indexer__max_objects;
293 		break;
294 
295 	case GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS:
296 		git_disable_pack_keep_file_checks = (va_arg(ap, int) != 0);
297 		break;
298 
299 	case GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE:
300 		git_http__expect_continue = (va_arg(ap, int) != 0);
301 		break;
302 
303 	default:
304 		git_error_set(GIT_ERROR_INVALID, "invalid option key");
305 		error = -1;
306 	}
307 
308 	va_end(ap);
309 
310 	return error;
311 }
312