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 "sysdir.h"
20 #include "cache.h"
21 #include "global.h"
22 #include "object.h"
23 #include "odb.h"
24 #include "refs.h"
25 #include "transports/smart.h"
26 #include "streams/openssl.h"
27 #include "streams/mbedtls.h"
28 
git_libgit2_version(int * major,int * minor,int * rev)29 void git_libgit2_version(int *major, int *minor, int *rev)
30 {
31 	*major = LIBGIT2_VER_MAJOR;
32 	*minor = LIBGIT2_VER_MINOR;
33 	*rev = LIBGIT2_VER_REVISION;
34 }
35 
git_libgit2_features(void)36 int git_libgit2_features(void)
37 {
38 	return 0
39 #ifdef GIT_THREADS
40 		| GIT_FEATURE_THREADS
41 #endif
42 #ifdef GIT_HTTPS
43 		| GIT_FEATURE_HTTPS
44 #endif
45 #if defined(GIT_SSH)
46 		| GIT_FEATURE_SSH
47 #endif
48 #if defined(GIT_USE_NSEC)
49 		| GIT_FEATURE_NSEC
50 #endif
51 	;
52 }
53 
54 /* Declarations for tuneable settings */
55 extern size_t git_mwindow__window_size;
56 extern size_t git_mwindow__mapped_limit;
57 
config_level_to_sysdir(int config_level)58 static int config_level_to_sysdir(int config_level)
59 {
60 	int val = -1;
61 
62 	switch (config_level) {
63 	case GIT_CONFIG_LEVEL_SYSTEM:
64 		val = GIT_SYSDIR_SYSTEM;
65 		break;
66 	case GIT_CONFIG_LEVEL_XDG:
67 		val = GIT_SYSDIR_XDG;
68 		break;
69 	case GIT_CONFIG_LEVEL_GLOBAL:
70 		val = GIT_SYSDIR_GLOBAL;
71 		break;
72 	case GIT_CONFIG_LEVEL_PROGRAMDATA:
73 		val = GIT_SYSDIR_PROGRAMDATA;
74 		break;
75 	default:
76 		giterr_set(
77 			GITERR_INVALID, "invalid config path selector %d", config_level);
78 	}
79 
80 	return val;
81 }
82 
83 extern char *git__user_agent;
84 extern char *git__ssl_ciphers;
85 
git_libgit2__user_agent(void)86 const char *git_libgit2__user_agent(void)
87 {
88 	return git__user_agent;
89 }
90 
git_libgit2__ssl_ciphers(void)91 const char *git_libgit2__ssl_ciphers(void)
92 {
93 	return git__ssl_ciphers;
94 }
95 
git_libgit2_opts(int key,...)96 int git_libgit2_opts(int key, ...)
97 {
98 	int error = 0;
99 	va_list ap;
100 
101 	va_start(ap, key);
102 
103 	switch (key) {
104 	case GIT_OPT_SET_MWINDOW_SIZE:
105 		git_mwindow__window_size = va_arg(ap, size_t);
106 		break;
107 
108 	case GIT_OPT_GET_MWINDOW_SIZE:
109 		*(va_arg(ap, size_t *)) = git_mwindow__window_size;
110 		break;
111 
112 	case GIT_OPT_SET_MWINDOW_MAPPED_LIMIT:
113 		git_mwindow__mapped_limit = va_arg(ap, size_t);
114 		break;
115 
116 	case GIT_OPT_GET_MWINDOW_MAPPED_LIMIT:
117 		*(va_arg(ap, size_t *)) = git_mwindow__mapped_limit;
118 		break;
119 
120 	case GIT_OPT_GET_SEARCH_PATH:
121 		if ((error = config_level_to_sysdir(va_arg(ap, int))) >= 0) {
122 			git_buf *out = va_arg(ap, git_buf *);
123 			const git_buf *tmp;
124 
125 			git_buf_sanitize(out);
126 			if ((error = git_sysdir_get(&tmp, error)) < 0)
127 				break;
128 
129 			error = git_buf_sets(out, tmp->ptr);
130 		}
131 		break;
132 
133 	case GIT_OPT_SET_SEARCH_PATH:
134 		if ((error = config_level_to_sysdir(va_arg(ap, int))) >= 0)
135 			error = git_sysdir_set(error, va_arg(ap, const char *));
136 		break;
137 
138 	case GIT_OPT_SET_CACHE_OBJECT_LIMIT:
139 		{
140 			git_otype type = (git_otype)va_arg(ap, int);
141 			size_t size = va_arg(ap, size_t);
142 			error = git_cache_set_max_object_size(type, size);
143 			break;
144 		}
145 
146 	case GIT_OPT_SET_CACHE_MAX_SIZE:
147 		git_cache__max_storage = va_arg(ap, ssize_t);
148 		break;
149 
150 	case GIT_OPT_ENABLE_CACHING:
151 		git_cache__enabled = (va_arg(ap, int) != 0);
152 		break;
153 
154 	case GIT_OPT_GET_CACHED_MEMORY:
155 		*(va_arg(ap, ssize_t *)) = git_cache__current_storage.val;
156 		*(va_arg(ap, ssize_t *)) = git_cache__max_storage;
157 		break;
158 
159 	case GIT_OPT_GET_TEMPLATE_PATH:
160 		{
161 			git_buf *out = va_arg(ap, git_buf *);
162 			const git_buf *tmp;
163 
164 			git_buf_sanitize(out);
165 			if ((error = git_sysdir_get(&tmp, GIT_SYSDIR_TEMPLATE)) < 0)
166 				break;
167 
168 			error = git_buf_sets(out, tmp->ptr);
169 		}
170 		break;
171 
172 	case GIT_OPT_SET_TEMPLATE_PATH:
173 		error = git_sysdir_set(GIT_SYSDIR_TEMPLATE, va_arg(ap, const char *));
174 		break;
175 
176 	case GIT_OPT_SET_SSL_CERT_LOCATIONS:
177 #ifdef GIT_OPENSSL
178 		{
179 			const char *file = va_arg(ap, const char *);
180 			const char *path = va_arg(ap, const char *);
181 			error = git_openssl__set_cert_location(file, path);
182 		}
183 #elif defined(GIT_MBEDTLS)
184 		{
185 			const char *file = va_arg(ap, const char *);
186 			const char *path = va_arg(ap, const char *);
187 			if (file)
188 				error = git_mbedtls__set_cert_location(file, 0);
189 			if (error && path)
190 				error = git_mbedtls__set_cert_location(path, 1);
191 		}
192 #else
193 		giterr_set(GITERR_SSL, "TLS backend doesn't support certificate locations");
194 		error = -1;
195 #endif
196 		break;
197 	case GIT_OPT_SET_USER_AGENT:
198 		git__free(git__user_agent);
199 		git__user_agent = git__strdup(va_arg(ap, const char *));
200 		if (!git__user_agent) {
201 			giterr_set_oom();
202 			error = -1;
203 		}
204 
205 		break;
206 
207 	case GIT_OPT_ENABLE_STRICT_OBJECT_CREATION:
208 		git_object__strict_input_validation = (va_arg(ap, int) != 0);
209 		break;
210 
211 	case GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION:
212 		git_reference__enable_symbolic_ref_target_validation = (va_arg(ap, int) != 0);
213 		break;
214 
215 	case GIT_OPT_SET_SSL_CIPHERS:
216 #if (GIT_OPENSSL || GIT_MBEDTLS)
217 		{
218 			git__free(git__ssl_ciphers);
219 			git__ssl_ciphers = git__strdup(va_arg(ap, const char *));
220 			if (!git__ssl_ciphers) {
221 				giterr_set_oom();
222 				error = -1;
223 			}
224 		}
225 #else
226 		giterr_set(GITERR_SSL, "TLS backend doesn't support custom ciphers");
227 		error = -1;
228 #endif
229 		break;
230 
231 	case GIT_OPT_GET_USER_AGENT:
232 		{
233 			git_buf *out = va_arg(ap, git_buf *);
234 			git_buf_sanitize(out);
235 			error = git_buf_sets(out, git__user_agent);
236 		}
237 		break;
238 
239 	case GIT_OPT_ENABLE_OFS_DELTA:
240 		git_smart__ofs_delta_enabled = (va_arg(ap, int) != 0);
241 		break;
242 
243 	case GIT_OPT_ENABLE_FSYNC_GITDIR:
244 		git_repository__fsync_gitdir = (va_arg(ap, int) != 0);
245 		break;
246 
247 	case GIT_OPT_GET_WINDOWS_SHAREMODE:
248 #ifdef GIT_WIN32
249 		*(va_arg(ap, unsigned long *)) = git_win32__createfile_sharemode;
250 #endif
251 		break;
252 
253 	case GIT_OPT_SET_WINDOWS_SHAREMODE:
254 #ifdef GIT_WIN32
255 		git_win32__createfile_sharemode = va_arg(ap, unsigned long);
256 #endif
257 		break;
258 
259 	case GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION:
260 		git_odb__strict_hash_verification = (va_arg(ap, int) != 0);
261 		break;
262 
263 	default:
264 		giterr_set(GITERR_INVALID, "invalid option key");
265 		error = -1;
266 	}
267 
268 	va_end(ap);
269 
270 	return error;
271 }
272 
273