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_indexer__max_objects;
63 extern bool git_disable_pack_keep_file_checks;
64 
config_level_to_sysdir(int config_level)65 static int config_level_to_sysdir(int config_level)
66 {
67 	int val = -1;
68 
69 	switch (config_level) {
70 	case GIT_CONFIG_LEVEL_SYSTEM:
71 		val = GIT_SYSDIR_SYSTEM;
72 		break;
73 	case GIT_CONFIG_LEVEL_XDG:
74 		val = GIT_SYSDIR_XDG;
75 		break;
76 	case GIT_CONFIG_LEVEL_GLOBAL:
77 		val = GIT_SYSDIR_GLOBAL;
78 		break;
79 	case GIT_CONFIG_LEVEL_PROGRAMDATA:
80 		val = GIT_SYSDIR_PROGRAMDATA;
81 		break;
82 	default:
83 		git_error_set(
84 			GIT_ERROR_INVALID, "invalid config path selector %d", config_level);
85 	}
86 
87 	return val;
88 }
89 
90 extern char *git__user_agent;
91 extern char *git__ssl_ciphers;
92 
git_libgit2__user_agent(void)93 const char *git_libgit2__user_agent(void)
94 {
95 	return git__user_agent;
96 }
97 
git_libgit2__ssl_ciphers(void)98 const char *git_libgit2__ssl_ciphers(void)
99 {
100 	return git__ssl_ciphers;
101 }
102 
git_libgit2_opts(int key,...)103 int git_libgit2_opts(int key, ...)
104 {
105 	int error = 0;
106 	va_list ap;
107 
108 	va_start(ap, key);
109 
110 	switch (key) {
111 	case GIT_OPT_SET_MWINDOW_SIZE:
112 		git_mwindow__window_size = va_arg(ap, size_t);
113 		break;
114 
115 	case GIT_OPT_GET_MWINDOW_SIZE:
116 		*(va_arg(ap, size_t *)) = git_mwindow__window_size;
117 		break;
118 
119 	case GIT_OPT_SET_MWINDOW_MAPPED_LIMIT:
120 		git_mwindow__mapped_limit = va_arg(ap, size_t);
121 		break;
122 
123 	case GIT_OPT_GET_MWINDOW_MAPPED_LIMIT:
124 		*(va_arg(ap, size_t *)) = git_mwindow__mapped_limit;
125 		break;
126 
127 	case GIT_OPT_GET_SEARCH_PATH:
128 		if ((error = config_level_to_sysdir(va_arg(ap, int))) >= 0) {
129 			git_buf *out = va_arg(ap, git_buf *);
130 			const git_buf *tmp;
131 
132 			git_buf_sanitize(out);
133 			if ((error = git_sysdir_get(&tmp, error)) < 0)
134 				break;
135 
136 			error = git_buf_sets(out, tmp->ptr);
137 		}
138 		break;
139 
140 	case GIT_OPT_SET_SEARCH_PATH:
141 		if ((error = config_level_to_sysdir(va_arg(ap, int))) >= 0)
142 			error = git_sysdir_set(error, va_arg(ap, const char *));
143 		break;
144 
145 	case GIT_OPT_SET_CACHE_OBJECT_LIMIT:
146 		{
147 			git_object_t type = (git_object_t)va_arg(ap, int);
148 			size_t size = va_arg(ap, size_t);
149 			error = git_cache_set_max_object_size(type, size);
150 			break;
151 		}
152 
153 	case GIT_OPT_SET_CACHE_MAX_SIZE:
154 		git_cache__max_storage = va_arg(ap, ssize_t);
155 		break;
156 
157 	case GIT_OPT_ENABLE_CACHING:
158 		git_cache__enabled = (va_arg(ap, int) != 0);
159 		break;
160 
161 	case GIT_OPT_GET_CACHED_MEMORY:
162 		*(va_arg(ap, ssize_t *)) = git_cache__current_storage.val;
163 		*(va_arg(ap, ssize_t *)) = git_cache__max_storage;
164 		break;
165 
166 	case GIT_OPT_GET_TEMPLATE_PATH:
167 		{
168 			git_buf *out = va_arg(ap, git_buf *);
169 			const git_buf *tmp;
170 
171 			git_buf_sanitize(out);
172 			if ((error = git_sysdir_get(&tmp, GIT_SYSDIR_TEMPLATE)) < 0)
173 				break;
174 
175 			error = git_buf_sets(out, tmp->ptr);
176 		}
177 		break;
178 
179 	case GIT_OPT_SET_TEMPLATE_PATH:
180 		error = git_sysdir_set(GIT_SYSDIR_TEMPLATE, va_arg(ap, const char *));
181 		break;
182 
183 	case GIT_OPT_SET_SSL_CERT_LOCATIONS:
184 #ifdef GIT_OPENSSL
185 		{
186 			const char *file = va_arg(ap, const char *);
187 			const char *path = va_arg(ap, const char *);
188 			error = git_openssl__set_cert_location(file, path);
189 		}
190 #elif defined(GIT_MBEDTLS)
191 		{
192 			const char *file = va_arg(ap, const char *);
193 			const char *path = va_arg(ap, const char *);
194 			if (file)
195 				error = git_mbedtls__set_cert_location(file, 0);
196 			if (error && path)
197 				error = git_mbedtls__set_cert_location(path, 1);
198 		}
199 #else
200 		git_error_set(GIT_ERROR_SSL, "TLS backend doesn't support certificate locations");
201 		error = -1;
202 #endif
203 		break;
204 	case GIT_OPT_SET_USER_AGENT:
205 		git__free(git__user_agent);
206 		git__user_agent = git__strdup(va_arg(ap, const char *));
207 		if (!git__user_agent) {
208 			git_error_set_oom();
209 			error = -1;
210 		}
211 
212 		break;
213 
214 	case GIT_OPT_ENABLE_STRICT_OBJECT_CREATION:
215 		git_object__strict_input_validation = (va_arg(ap, int) != 0);
216 		break;
217 
218 	case GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION:
219 		git_reference__enable_symbolic_ref_target_validation = (va_arg(ap, int) != 0);
220 		break;
221 
222 	case GIT_OPT_SET_SSL_CIPHERS:
223 #if (GIT_OPENSSL || GIT_MBEDTLS)
224 		{
225 			git__free(git__ssl_ciphers);
226 			git__ssl_ciphers = git__strdup(va_arg(ap, const char *));
227 			if (!git__ssl_ciphers) {
228 				git_error_set_oom();
229 				error = -1;
230 			}
231 		}
232 #else
233 		git_error_set(GIT_ERROR_SSL, "TLS backend doesn't support custom ciphers");
234 		error = -1;
235 #endif
236 		break;
237 
238 	case GIT_OPT_GET_USER_AGENT:
239 		{
240 			git_buf *out = va_arg(ap, git_buf *);
241 			git_buf_sanitize(out);
242 			error = git_buf_sets(out, git__user_agent);
243 		}
244 		break;
245 
246 	case GIT_OPT_ENABLE_OFS_DELTA:
247 		git_smart__ofs_delta_enabled = (va_arg(ap, int) != 0);
248 		break;
249 
250 	case GIT_OPT_ENABLE_FSYNC_GITDIR:
251 		git_repository__fsync_gitdir = (va_arg(ap, int) != 0);
252 		break;
253 
254 	case GIT_OPT_GET_WINDOWS_SHAREMODE:
255 #ifdef GIT_WIN32
256 		*(va_arg(ap, unsigned long *)) = git_win32__createfile_sharemode;
257 #endif
258 		break;
259 
260 	case GIT_OPT_SET_WINDOWS_SHAREMODE:
261 #ifdef GIT_WIN32
262 		git_win32__createfile_sharemode = va_arg(ap, unsigned long);
263 #endif
264 		break;
265 
266 	case GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION:
267 		git_odb__strict_hash_verification = (va_arg(ap, int) != 0);
268 		break;
269 
270 	case GIT_OPT_SET_ALLOCATOR:
271 		error = git_allocator_setup(va_arg(ap, git_allocator *));
272 		break;
273 
274 	case GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY:
275 		git_index__enforce_unsaved_safety = (va_arg(ap, int) != 0);
276 		break;
277 
278 	case GIT_OPT_SET_PACK_MAX_OBJECTS:
279 		git_indexer__max_objects = va_arg(ap, size_t);
280 		break;
281 
282 	case GIT_OPT_GET_PACK_MAX_OBJECTS:
283 		*(va_arg(ap, size_t *)) = git_indexer__max_objects;
284 		break;
285 
286 	case GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS:
287 		git_disable_pack_keep_file_checks = (va_arg(ap, int) != 0);
288 		break;
289 
290 	case GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE:
291 		git_http__expect_continue = (va_arg(ap, int) != 0);
292 		break;
293 
294 	default:
295 		git_error_set(GIT_ERROR_INVALID, "invalid option key");
296 		error = -1;
297 	}
298 
299 	va_end(ap);
300 
301 	return error;
302 }
303