88
enum allow_uor allow_uor;
89
90
struct list_objects_filter_options filter_options;
91
+ struct string_list allowed_filters;
92
93
struct packet_writer writer;
94
104
unsigned no_progress : 1;
105
unsigned use_include_tag : 1;
106
unsigned allow_filter : 1;
107
+ unsigned allow_filter_fallback : 1;
108
109
unsigned done : 1; /* v2 only */
110
unsigned allow_ref_in_want : 1; /* v2 only */
122
struct string_list deepen_not = STRING_LIST_INIT_DUP;
123
struct string_list uri_protocols = STRING_LIST_INIT_DUP;
124
struct object_array extra_edge_obj = OBJECT_ARRAY_INIT;
125
+ struct string_list allowed_filters = STRING_LIST_INIT_DUP;
126
127
memset(data, 0, sizeof(*data));
128
data->symref = symref;
134
data->deepen_not = deepen_not;
135
data->uri_protocols = uri_protocols;
136
data->extra_edge_obj = extra_edge_obj;
137
+ data->allowed_filters = allowed_filters;
138
+ data->allow_filter_fallback = 1;
139
packet_writer_init(&data->writer, 1);
140
141
data->keepalive = 5;
152
string_list_clear(&data->deepen_not, 0);
153
object_array_clear(&data->extra_edge_obj);
154
list_objects_filter_release(&data->filter_options);
155
+ string_list_clear(&data->allowed_filters, 1);
156
157
free((char *)data->pack_objects_hook);
158
}
989
return 0;
990
}
991
992
+NORETURN __attribute__((format(printf,2,3)))
993
+static void send_err_and_die(struct upload_pack_data *data,
994
+ const char *fmt, ...)
995
+{
996
+ struct strbuf buf = STRBUF_INIT;
997
+ va_list ap;
998
+
999
+ va_start(ap, fmt);
1000
+ strbuf_vaddf(&buf, fmt, ap);
1001
+ va_end(ap);
1002
+
1003
+ packet_writer_error(&data->writer, "%s", buf.buf);
1004
+ die("%s", buf.buf);
1005
+}
1006
+
1007
+static void check_one_filter(struct upload_pack_data *data,
1008
+ struct list_objects_filter_options *opts)
1009
+{
1010
+ const char *key = list_object_filter_config_name(opts->choice);
1011
+ struct string_list_item *item = string_list_lookup(&data->allowed_filters,
1012
+ key);
1013
+ int allowed;
1014
+
1015
+ if (item)
1016
+ allowed = (intptr_t)item->util;
1017
+ else
1018
+ allowed = data->allow_filter_fallback;
1019
+
1020
+ if (!allowed)
1021
+ send_err_and_die(data, "filter '%s' not supported", key);
1022
+}
1023
+
1024
+static void check_filter_recurse(struct upload_pack_data *data,
1025
+ struct list_objects_filter_options *opts)
1026
+{
1027
+ size_t i;
1028
+
1029
+ check_one_filter(data, opts);
1030
+ if (opts->choice != LOFC_COMBINE)
1031
+ return;
1032
+
1033
+ for (i = 0; i < opts->sub_nr; i++)
1034
+ check_filter_recurse(data, &opts->sub[i]);
1035
+}
1036
+
1037
+static void die_if_using_banned_filter(struct upload_pack_data *data)
1038
+{
1039
+ check_filter_recurse(data, &data->filter_options);
1040
+}
1041
+
1042
static void receive_needs(struct upload_pack_data *data,
1043
struct packet_reader *reader)
1044
{
1069
die("git upload-pack: filtering capability not negotiated");
1070
list_objects_filter_die_if_populated(&data->filter_options);
1071
parse_list_objects_filter(&data->filter_options, arg);
1072
+ die_if_using_banned_filter(data);
1073
continue;
1074
}
1075
1226
return 0;
1227
}
1228
1229
+static int parse_object_filter_config(const char *var, const char *value,
1230
+ struct upload_pack_data *data)
1231
+{
1232
+ struct strbuf buf = STRBUF_INIT;
1233
+ const char *sub, *key;
1234
+ size_t sub_len;
1235
+
1236
+ if (parse_config_key(var, "uploadpackfilter", &sub, &sub_len, &key))
1237
+ return 0;
1238
+
1239
+ if (!sub) {
1240
+ if (!strcmp(key, "allow"))
1241
+ data->allow_filter_fallback = git_config_bool(var, value);
1242
+ return 0;
1243
+ }
1244
+
1245
+ strbuf_add(&buf, sub, sub_len);
1246
+
1247
+ if (!strcmp(key, "allow"))
1248
+ string_list_insert(&data->allowed_filters, buf.buf)->util =
1249
+ (void *)(intptr_t)git_config_bool(var, value);
1250
+
1251
+ strbuf_release(&buf);
1252
+ return 0;
1253
+}
1254
+
1255
static int upload_pack_config(const char *var, const char *value, void *cb_data)
1256
{
1257
struct upload_pack_data *data = cb_data;
1291
return git_config_string(&data->pack_objects_hook, var, value);
1292
}
1293
1294
+ parse_object_filter_config(var, value, data);
1295
+
1296
return parse_hide_refs_config(var, value, "uploadpack");
1297
}
1298
1473
if (data->allow_filter && skip_prefix(arg, "filter ", &p)) {
1474
list_objects_filter_die_if_populated(&data->filter_options);
1475
parse_list_objects_filter(&data->filter_options, p);
1476
+ die_if_using_banned_filter(data);
1477
continue;
1478
}
1479