summaryrefslogtreecommitdiff
path: root/kex.c
diff options
context:
space:
mode:
Diffstat (limited to 'kex.c')
-rw-r--r--kex.c95
1 files changed, 78 insertions, 17 deletions
diff --git a/kex.c b/kex.c
index d0a5f1b66..2fd052e96 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.137 2018/07/03 11:39:54 djm Exp $ */ 1/* $OpenBSD: kex.c,v 1.138 2018/07/04 13:49:31 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -174,7 +174,7 @@ kex_names_cat(const char *a, const char *b)
174 size_t len; 174 size_t len;
175 175
176 if (a == NULL || *a == '\0') 176 if (a == NULL || *a == '\0')
177 return NULL; 177 return strdup(b);
178 if (b == NULL || *b == '\0') 178 if (b == NULL || *b == '\0')
179 return strdup(a); 179 return strdup(a);
180 if (strlen(b) > 1024*1024) 180 if (strlen(b) > 1024*1024)
@@ -209,27 +209,88 @@ kex_names_cat(const char *a, const char *b)
209 * specified names should be removed. 209 * specified names should be removed.
210 */ 210 */
211int 211int
212kex_assemble_names(const char *def, char **list) 212kex_assemble_names(char **listp, const char *def, const char *all)
213{ 213{
214 char *ret; 214 char *cp, *tmp, *patterns;
215 char *list = NULL, *ret = NULL, *matching = NULL, *opatterns = NULL;
216 int r = SSH_ERR_INTERNAL_ERROR;
215 217
216 if (list == NULL || *list == NULL || **list == '\0') { 218 if (listp == NULL || *listp == NULL || **listp == '\0') {
217 *list = strdup(def); 219 if ((*listp = strdup(def)) == NULL)
220 return SSH_ERR_ALLOC_FAIL;
218 return 0; 221 return 0;
219 } 222 }
220 if (**list == '+') { 223
221 if ((ret = kex_names_cat(def, *list + 1)) == NULL) 224 list = *listp;
222 return SSH_ERR_ALLOC_FAIL; 225 *listp = NULL;
223 free(*list); 226 if (*list == '+') {
224 *list = ret; 227 /* Append names to default list */
225 } else if (**list == '-') { 228 if ((tmp = kex_names_cat(def, list + 1)) == NULL) {
226 if ((ret = match_filter_list(def, *list + 1)) == NULL) 229 r = SSH_ERR_ALLOC_FAIL;
227 return SSH_ERR_ALLOC_FAIL; 230 goto fail;
228 free(*list); 231 }
229 *list = ret; 232 free(list);
233 list = tmp;
234 } else if (*list == '-') {
235 /* Remove names from default list */
236 if ((*listp = match_filter_blacklist(def, list + 1)) == NULL) {
237 r = SSH_ERR_ALLOC_FAIL;
238 goto fail;
239 }
240 free(list);
241 /* filtering has already been done */
242 return 0;
243 } else {
244 /* Explicit list, overrides default - just use "list" as is */
230 } 245 }
231 246
232 return 0; 247 /*
248 * The supplied names may be a pattern-list. For the -list case,
249 * the patterns are applied above. For the +list and explicit list
250 * cases we need to do it now.
251 */
252 ret = NULL;
253 if ((patterns = opatterns = strdup(list)) == NULL) {
254 r = SSH_ERR_ALLOC_FAIL;
255 goto fail;
256 }
257 /* Apply positive (i.e. non-negated) patterns from the list */
258 while ((cp = strsep(&patterns, ",")) != NULL) {
259 if (*cp == '!') {
260 /* negated matches are not supported here */
261 r = SSH_ERR_INVALID_ARGUMENT;
262 goto fail;
263 }
264 free(matching);
265 if ((matching = match_filter_whitelist(all, cp)) == NULL) {
266 r = SSH_ERR_ALLOC_FAIL;
267 goto fail;
268 }
269 if ((tmp = kex_names_cat(ret, matching)) == NULL) {
270 r = SSH_ERR_ALLOC_FAIL;
271 goto fail;
272 }
273 free(ret);
274 ret = tmp;
275 }
276 if (ret == NULL || *ret == '\0') {
277 /* An empty name-list is an error */
278 /* XXX better error code? */
279 r = SSH_ERR_INVALID_ARGUMENT;
280 goto fail;
281 }
282
283 /* success */
284 *listp = ret;
285 ret = NULL;
286 r = 0;
287
288 fail:
289 free(matching);
290 free(opatterns);
291 free(list);
292 free(ret);
293 return r;
233} 294}
234 295
235/* put algorithm proposal into buffer */ 296/* put algorithm proposal into buffer */