Blame


1 bd3d9e54 2021-09-05 stsp /*
2 bd3d9e54 2021-09-05 stsp * Copyright (c) 2019 Ori Bernstein <ori@openbsd.org>
3 bd3d9e54 2021-09-05 stsp * Copyright (c) 2021 Stefan Sperling <stsp@openbsd.org>
4 bd3d9e54 2021-09-05 stsp *
5 bd3d9e54 2021-09-05 stsp * Permission to use, copy, modify, and distribute this software for any
6 bd3d9e54 2021-09-05 stsp * purpose with or without fee is hereby granted, provided that the above
7 bd3d9e54 2021-09-05 stsp * copyright notice and this permission notice appear in all copies.
8 bd3d9e54 2021-09-05 stsp *
9 bd3d9e54 2021-09-05 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 bd3d9e54 2021-09-05 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 bd3d9e54 2021-09-05 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 bd3d9e54 2021-09-05 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 bd3d9e54 2021-09-05 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 bd3d9e54 2021-09-05 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 bd3d9e54 2021-09-05 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 bd3d9e54 2021-09-05 stsp */
17 bd3d9e54 2021-09-05 stsp
18 bd3d9e54 2021-09-05 stsp #include <sys/queue.h>
19 8a8621c2 2021-09-06 naddy #include <sys/types.h>
20 bd3d9e54 2021-09-05 stsp
21 bd3d9e54 2021-09-05 stsp #include <ctype.h>
22 bd3d9e54 2021-09-05 stsp #include <stdio.h>
23 bd3d9e54 2021-09-05 stsp #include <stdlib.h>
24 bd3d9e54 2021-09-05 stsp #include <string.h>
25 bd3d9e54 2021-09-05 stsp
26 bd3d9e54 2021-09-05 stsp #include "got_error.h"
27 bd3d9e54 2021-09-05 stsp #include "got_path.h"
28 bd3d9e54 2021-09-05 stsp
29 bd3d9e54 2021-09-05 stsp #include "got_lib_gitproto.h"
30 bd3d9e54 2021-09-05 stsp
31 bd3d9e54 2021-09-05 stsp #ifndef nitems
32 bd3d9e54 2021-09-05 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
33 bd3d9e54 2021-09-05 stsp #endif
34 bd3d9e54 2021-09-05 stsp
35 bd3d9e54 2021-09-05 stsp static const struct got_error *
36 bd3d9e54 2021-09-05 stsp tokenize_refline(char **tokens, char *line, int len, int maxtokens)
37 bd3d9e54 2021-09-05 stsp {
38 bd3d9e54 2021-09-05 stsp const struct got_error *err = NULL;
39 bd3d9e54 2021-09-05 stsp char *p;
40 bd3d9e54 2021-09-05 stsp size_t i, n = 0;
41 bd3d9e54 2021-09-05 stsp
42 bd3d9e54 2021-09-05 stsp for (i = 0; i < maxtokens; i++)
43 bd3d9e54 2021-09-05 stsp tokens[i] = NULL;
44 bd3d9e54 2021-09-05 stsp
45 bd3d9e54 2021-09-05 stsp for (i = 0; n < len && i < maxtokens; i++) {
46 bd3d9e54 2021-09-05 stsp while (isspace(*line)) {
47 bd3d9e54 2021-09-05 stsp line++;
48 bd3d9e54 2021-09-05 stsp n++;
49 bd3d9e54 2021-09-05 stsp }
50 bd3d9e54 2021-09-05 stsp p = line;
51 bd3d9e54 2021-09-05 stsp while (*line != '\0' && n < len &&
52 bd3d9e54 2021-09-05 stsp (!isspace(*line) || i == maxtokens - 1)) {
53 bd3d9e54 2021-09-05 stsp line++;
54 bd3d9e54 2021-09-05 stsp n++;
55 bd3d9e54 2021-09-05 stsp }
56 bd3d9e54 2021-09-05 stsp tokens[i] = strndup(p, line - p);
57 bd3d9e54 2021-09-05 stsp if (tokens[i] == NULL) {
58 bd3d9e54 2021-09-05 stsp err = got_error_from_errno("strndup");
59 bd3d9e54 2021-09-05 stsp goto done;
60 bd3d9e54 2021-09-05 stsp }
61 bd3d9e54 2021-09-05 stsp /* Skip \0 field-delimiter at end of token. */
62 bd3d9e54 2021-09-05 stsp while (line[0] == '\0' && n < len) {
63 bd3d9e54 2021-09-05 stsp line++;
64 bd3d9e54 2021-09-05 stsp n++;
65 bd3d9e54 2021-09-05 stsp }
66 bd3d9e54 2021-09-05 stsp }
67 bd3d9e54 2021-09-05 stsp if (i <= 2)
68 bd3d9e54 2021-09-05 stsp err = got_error(GOT_ERR_BAD_PACKET);
69 bd3d9e54 2021-09-05 stsp done:
70 bd3d9e54 2021-09-05 stsp if (err) {
71 bd3d9e54 2021-09-05 stsp int j;
72 bd3d9e54 2021-09-05 stsp for (j = 0; j < i; j++) {
73 bd3d9e54 2021-09-05 stsp free(tokens[j]);
74 bd3d9e54 2021-09-05 stsp tokens[j] = NULL;
75 bd3d9e54 2021-09-05 stsp }
76 bd3d9e54 2021-09-05 stsp }
77 bd3d9e54 2021-09-05 stsp return err;
78 bd3d9e54 2021-09-05 stsp }
79 bd3d9e54 2021-09-05 stsp
80 bd3d9e54 2021-09-05 stsp const struct got_error *
81 bd3d9e54 2021-09-05 stsp got_gitproto_parse_refline(char **id_str, char **refname,
82 bd3d9e54 2021-09-05 stsp char **server_capabilities, char *line, int len)
83 bd3d9e54 2021-09-05 stsp {
84 bd3d9e54 2021-09-05 stsp const struct got_error *err = NULL;
85 bd3d9e54 2021-09-05 stsp char *tokens[3];
86 bd3d9e54 2021-09-05 stsp
87 e99d9267 2021-10-07 stsp *id_str = NULL;
88 e99d9267 2021-10-07 stsp *refname = NULL;
89 e99d9267 2021-10-07 stsp /* don't reset *server_capabilities */
90 e99d9267 2021-10-07 stsp
91 bd3d9e54 2021-09-05 stsp err = tokenize_refline(tokens, line, len, nitems(tokens));
92 bd3d9e54 2021-09-05 stsp if (err)
93 bd3d9e54 2021-09-05 stsp return err;
94 bd3d9e54 2021-09-05 stsp
95 bd3d9e54 2021-09-05 stsp if (tokens[0])
96 bd3d9e54 2021-09-05 stsp *id_str = tokens[0];
97 bd3d9e54 2021-09-05 stsp if (tokens[1])
98 bd3d9e54 2021-09-05 stsp *refname = tokens[1];
99 bd3d9e54 2021-09-05 stsp if (tokens[2]) {
100 e99d9267 2021-10-07 stsp if (*server_capabilities == NULL) {
101 e99d9267 2021-10-07 stsp char *p;
102 e99d9267 2021-10-07 stsp *server_capabilities = tokens[2];
103 e99d9267 2021-10-07 stsp p = strrchr(*server_capabilities, '\n');
104 e99d9267 2021-10-07 stsp if (p)
105 e99d9267 2021-10-07 stsp *p = '\0';
106 e99d9267 2021-10-07 stsp } else
107 e99d9267 2021-10-07 stsp free(tokens[2]);
108 bd3d9e54 2021-09-05 stsp }
109 bd3d9e54 2021-09-05 stsp
110 bd3d9e54 2021-09-05 stsp return NULL;
111 bd3d9e54 2021-09-05 stsp }
112 bd3d9e54 2021-09-05 stsp
113 bd3d9e54 2021-09-05 stsp static const struct got_error *
114 bd3d9e54 2021-09-05 stsp match_capability(char **my_capabilities, const char *capa,
115 bd3d9e54 2021-09-05 stsp const struct got_capability *mycapa)
116 bd3d9e54 2021-09-05 stsp {
117 bd3d9e54 2021-09-05 stsp char *equalsign;
118 bd3d9e54 2021-09-05 stsp char *s;
119 bd3d9e54 2021-09-05 stsp
120 bd3d9e54 2021-09-05 stsp equalsign = strchr(capa, '=');
121 bd3d9e54 2021-09-05 stsp if (equalsign) {
122 bd3d9e54 2021-09-05 stsp if (strncmp(capa, mycapa->key, equalsign - capa) != 0)
123 bd3d9e54 2021-09-05 stsp return NULL;
124 bd3d9e54 2021-09-05 stsp } else {
125 bd3d9e54 2021-09-05 stsp if (strcmp(capa, mycapa->key) != 0)
126 bd3d9e54 2021-09-05 stsp return NULL;
127 bd3d9e54 2021-09-05 stsp }
128 bd3d9e54 2021-09-05 stsp
129 bd3d9e54 2021-09-05 stsp if (asprintf(&s, "%s %s%s%s",
130 bd3d9e54 2021-09-05 stsp *my_capabilities != NULL ? *my_capabilities : "",
131 bd3d9e54 2021-09-05 stsp mycapa->key,
132 bd3d9e54 2021-09-05 stsp mycapa->value != NULL ? "=" : "",
133 e33e440b 2021-09-05 stsp mycapa->value != NULL ? mycapa->value : "") == -1)
134 bd3d9e54 2021-09-05 stsp return got_error_from_errno("asprintf");
135 bd3d9e54 2021-09-05 stsp
136 bd3d9e54 2021-09-05 stsp free(*my_capabilities);
137 bd3d9e54 2021-09-05 stsp *my_capabilities = s;
138 bd3d9e54 2021-09-05 stsp return NULL;
139 bd3d9e54 2021-09-05 stsp }
140 bd3d9e54 2021-09-05 stsp
141 bd3d9e54 2021-09-05 stsp static const struct got_error *
142 bd3d9e54 2021-09-05 stsp add_symref(struct got_pathlist_head *symrefs, char *capa)
143 bd3d9e54 2021-09-05 stsp {
144 bd3d9e54 2021-09-05 stsp const struct got_error *err = NULL;
145 bd3d9e54 2021-09-05 stsp char *colon, *name = NULL, *target = NULL;
146 bd3d9e54 2021-09-05 stsp
147 bd3d9e54 2021-09-05 stsp /* Need at least "A:B" */
148 bd3d9e54 2021-09-05 stsp if (strlen(capa) < 3)
149 bd3d9e54 2021-09-05 stsp return NULL;
150 bd3d9e54 2021-09-05 stsp
151 bd3d9e54 2021-09-05 stsp colon = strchr(capa, ':');
152 bd3d9e54 2021-09-05 stsp if (colon == NULL)
153 bd3d9e54 2021-09-05 stsp return NULL;
154 bd3d9e54 2021-09-05 stsp
155 bd3d9e54 2021-09-05 stsp *colon = '\0';
156 bd3d9e54 2021-09-05 stsp name = strdup(capa);
157 bd3d9e54 2021-09-05 stsp if (name == NULL)
158 bd3d9e54 2021-09-05 stsp return got_error_from_errno("strdup");
159 bd3d9e54 2021-09-05 stsp
160 bd3d9e54 2021-09-05 stsp target = strdup(colon + 1);
161 bd3d9e54 2021-09-05 stsp if (target == NULL) {
162 bd3d9e54 2021-09-05 stsp err = got_error_from_errno("strdup");
163 bd3d9e54 2021-09-05 stsp goto done;
164 bd3d9e54 2021-09-05 stsp }
165 bd3d9e54 2021-09-05 stsp
166 bd3d9e54 2021-09-05 stsp /* We can't validate the ref itself here. The main process will. */
167 bd3d9e54 2021-09-05 stsp err = got_pathlist_append(symrefs, name, target);
168 bd3d9e54 2021-09-05 stsp done:
169 bd3d9e54 2021-09-05 stsp if (err) {
170 bd3d9e54 2021-09-05 stsp free(name);
171 bd3d9e54 2021-09-05 stsp free(target);
172 bd3d9e54 2021-09-05 stsp }
173 bd3d9e54 2021-09-05 stsp return err;
174 bd3d9e54 2021-09-05 stsp }
175 bd3d9e54 2021-09-05 stsp
176 bd3d9e54 2021-09-05 stsp const struct got_error *
177 bd3d9e54 2021-09-05 stsp got_gitproto_match_capabilities(char **common_capabilities,
178 bd3d9e54 2021-09-05 stsp struct got_pathlist_head *symrefs, char *server_capabilities,
179 bd3d9e54 2021-09-05 stsp const struct got_capability my_capabilities[], size_t ncapa)
180 bd3d9e54 2021-09-05 stsp {
181 bd3d9e54 2021-09-05 stsp const struct got_error *err = NULL;
182 bd3d9e54 2021-09-05 stsp char *capa, *equalsign;
183 bd3d9e54 2021-09-05 stsp size_t i;
184 bd3d9e54 2021-09-05 stsp
185 bd3d9e54 2021-09-05 stsp *common_capabilities = NULL;
186 bd3d9e54 2021-09-05 stsp do {
187 bd3d9e54 2021-09-05 stsp capa = strsep(&server_capabilities, " ");
188 bd3d9e54 2021-09-05 stsp if (capa == NULL)
189 bd3d9e54 2021-09-05 stsp return NULL;
190 bd3d9e54 2021-09-05 stsp
191 bd3d9e54 2021-09-05 stsp equalsign = strchr(capa, '=');
192 bd3d9e54 2021-09-05 stsp if (equalsign != NULL && symrefs != NULL &&
193 bd3d9e54 2021-09-05 stsp strncmp(capa, "symref", equalsign - capa) == 0) {
194 bd3d9e54 2021-09-05 stsp err = add_symref(symrefs, equalsign + 1);
195 bd3d9e54 2021-09-05 stsp if (err)
196 bd3d9e54 2021-09-05 stsp break;
197 bd3d9e54 2021-09-05 stsp continue;
198 bd3d9e54 2021-09-05 stsp }
199 bd3d9e54 2021-09-05 stsp
200 bd3d9e54 2021-09-05 stsp for (i = 0; i < ncapa; i++) {
201 bd3d9e54 2021-09-05 stsp err = match_capability(common_capabilities,
202 bd3d9e54 2021-09-05 stsp capa, &my_capabilities[i]);
203 bd3d9e54 2021-09-05 stsp if (err)
204 bd3d9e54 2021-09-05 stsp break;
205 bd3d9e54 2021-09-05 stsp }
206 bd3d9e54 2021-09-05 stsp } while (capa);
207 bd3d9e54 2021-09-05 stsp
208 bd3d9e54 2021-09-05 stsp if (*common_capabilities == NULL) {
209 bd3d9e54 2021-09-05 stsp *common_capabilities = strdup("");
210 bd3d9e54 2021-09-05 stsp if (*common_capabilities == NULL)
211 bd3d9e54 2021-09-05 stsp err = got_error_from_errno("strdup");
212 bd3d9e54 2021-09-05 stsp }
213 bd3d9e54 2021-09-05 stsp return err;
214 bd3d9e54 2021-09-05 stsp }