1 /* { dg-do run } */
2 /* SEGV at comment below. */
3 typedef unsigned int size_t;
4 typedef enum har {
5 he_fatal = (-199),
6 he_not_initialized,
7 he_bad_input,
8 he_memory_too_small,
9 he_bad_action,
10 he_duplicate,
11 he_bad_nonce,
12 he_stale_nonce,
13 he_bad_credentials,
14 he_bad_user,
15 he_no_such_user,
16 he_bad_passwd,
17 he_unknown_auth_scheme,
18 he_not_found,
19 he_failed_digest_file_check,
20 he_failed_digest_file_save,
21 he_process_not_privileged,
22 he_other,
23 he_end_of_range,
24 ha_no_error = 0,
25 ha_no_value = 1
26 } har;
27 typedef enum realm_type
28 {
29 axis_realm = 0,
30 ws_realm
31 } realm_type;
32
33 __attribute__((__noclone__, __noinline__))
34 har has_www_auth(char *, size_t, realm_type, har);
35
36 __attribute__((__noclone__, __noinline__))
37 har has_auth_user(const char *, const char *, realm_type, char *, size_t);
38
39 __attribute__((__noclone__, __noinline__))
40 char *ha_get_string_value(void);
41
42 typedef struct
43 {
44 unsigned int track_id;
45 char* user;
46 char* realm;
47 char* authent;
48 int internal_realm;
49 } request;
50 enum user_response {
51 file_not_found_user_response = -3,
52 access_denied_user_response = -2,
53 no_user_response = -1,
54 ok_user_response = 0
55 };
56 struct realm_group {
57 char *name;
58 int id;
59 struct realm_group *next;
60 };
61 struct realm {
62 char *name;
63 char *space;
64 struct realm_group *groups;
65 struct realm *next;
66 };
67 struct user_info {
68 char *name;
69 int no_groups;
70 int groups[128];
71 struct user_info *next;
72 };
73 static struct user_info *find_user(const char *user_name);
74 static int is_member_of_groups(const struct user_info *user_item,
75 const struct realm_group *groups);
76 int authent_author(request *req);
77 struct realm *realms = ((void *)0);
78 struct user_info *users = ((void *)0);
79 static struct user_info*
find_user(const char * user_name)80 find_user(const char *user_name)
81 {
82 struct user_info *user_item;
83 user_item = users;
84 while (user_item != ((void *)0)) {
85 /* SEGV due to NULL access here on user_name. See also comment below. */
86 if ((__builtin_strcmp(user_item->name, user_name) == 0))
87 break;
88 user_item = user_item->next;
89 }
90 return user_item;
91 }
92 static int
is_member_of_groups(const struct user_info * user_item,const struct realm_group * groups)93 is_member_of_groups(const struct user_info *user_item,
94 const struct realm_group *groups)
95 {
96 const struct realm_group *group_item;
97 int i;
98 group_item = groups;
99 while (group_item != ((void *)0)) {
100 for (i = 0; i < user_item->no_groups; i++)
101 if (user_item->groups[i] == group_item->id)
102 return 0;
103 group_item = group_item->next;
104 }
105 return -1;
106 }
107 char *foo (void) __attribute__((__noclone__, __noinline__));
108 char* g_strdup (const char *str) __attribute__((__malloc__, __noclone__, __noinline__));
109 int g_strcmp0 (const char *str1, const char *str2);
110 static int
is_basic(char ** user)111 is_basic(char **user)
112 {
113 char *passwd_ptr;
114 char *authent = foo();
115 passwd_ptr = __builtin_strchr(authent, ':');
116 if (passwd_ptr != ((void *)0)) {
117 *user = g_strdup(authent);
118 return 0;
119 }
120 return -1;
121 }
122 static int
is_digest(char ** user)123 is_digest(char **user)
124 {
125 int ret_val = -1;
126 char *authent;
127 authent = ha_get_string_value();
128 if (authent) {
129 *user = g_strdup(authent);
130 ret_val = 0;
131 }
132 return ret_val;
133 }
134 __attribute__((__noclone__, __noinline__))
135 void g_free (void * mem);
136 static enum user_response
get_user_info_from_header(const realm_type type,char ** user_name,struct user_info ** user_item)137 get_user_info_from_header(const realm_type type,
138 char **user_name,
139 struct user_info **user_item)
140 {
141 int ret_val = no_user_response;
142 if ((type == ws_realm)) {
143 if (is_basic(user_name) == 0)
144 ret_val = access_denied_user_response;
145 if (is_digest(user_name) == 0)
146 ret_val = ok_user_response;
147 } else {
148 if (is_basic(user_name) < 0 &&
149 /* Load of *user_name here, but not after the is_digest call. */
150 is_digest(user_name) < 0)
151 ;
152 else if ((*user_item = find_user(*user_name)) != ((void *)0))
153 ret_val = ok_user_response;
154 else
155 ret_val = access_denied_user_response;
156 if (ret_val != ok_user_response)
157 g_free(*user_name);
158 }
159 return ret_val;
160 }
161 static enum user_response
authenticate_user(request * req,char ** user_name,struct user_info ** user_item)162 authenticate_user(request *req,
163 char **user_name,
164 struct user_info **user_item)
165 {
166 char *authent = ((void *)0);
167 har resp = ha_no_value;
168 enum user_response user_resp;
169 int ret_val = no_user_response;
170 if (req->authent && __builtin_strlen(req->authent)) {
171 authent = req->authent;
172 user_resp = get_user_info_from_header(req->internal_realm,
173 user_name,
174 user_item);
175 if (user_resp == ok_user_response) {
176 resp = has_auth_user(authent, 0, req->internal_realm, "", 1);
177 if (resp == ha_no_error)
178 ret_val = ok_user_response;
179 else if (resp != he_stale_nonce)
180 ret_val = access_denied_user_response;
181 } else if (user_resp == access_denied_user_response)
182 ret_val = access_denied_user_response;
183 }
184 if (resp != he_memory_too_small && resp != ha_no_error)
185 resp = has_www_auth("", 1, req->internal_realm, resp);
186 return ret_val;
187 }
188
189 int __attribute__ ((__noinline__, __noclone__))
authent_author(request * req)190 authent_author(request *req)
191 {
192 struct realm *realm;
193 char *user_name = ((void *)0);
194 struct user_info *user_item = ((void *)0);
195 int res = 0;
196 asm ("");
197 realm = realms;
198 if (__builtin_strcmp("Wsd", realm->name) == 0) {
199 req->internal_realm = ws_realm;
200 is_digest(&user_name);
201 }
202 if (authenticate_user(req, &user_name, &user_item) < 0) {
203 if (user_name != ((void *)0))
204 req->user = user_name;
205 res = -2;
206 goto authent_author_return;
207 }
208 if (is_member_of_groups(user_item, realm->groups) < 0)
209 res = -1;
210 authent_author_return:
211 return res;
212 }
213
214 int good0, good1, good2;
215
216 __attribute__ ((__noinline__, __noclone__))
foo(void)217 char *foo(void)
218 {
219 asm ("");
220 good0++;
221 return "";
222 }
223
224 __attribute__ ((__noinline__, __noclone__))
ha_get_string_value(void)225 char *ha_get_string_value(void)
226 {
227 asm ("");
228 good1++;
229 return "f";
230 }
231
232 __attribute__ ((__noinline__, __noclone__))
has_auth_user(const char * a,const char * b,realm_type c,char * d,size_t e)233 har has_auth_user(const char *a, const char *b, realm_type c, char *d, size_t e)
234 {
235 asm ("");
236 if (*a != 'z' || a[1] != 0 || b != 0 || c != axis_realm || *d != 0
237 || e != 1)
238 __builtin_abort ();
239 return ha_no_error;
240 }
241
242 __attribute__ ((__noinline__, __noclone__))
has_www_auth(char * a,size_t b,realm_type c,har d)243 har has_www_auth(char *a, size_t b, realm_type c, har d)
244 {
245 (void)(*a+b+c+d);
246 asm ("");
247 __builtin_abort ();
248 }
249
250
251 char *strdupped_user = "me";
252 __attribute__((__malloc__, __noclone__, __noinline__))
g_strdup(const char * str)253 char* g_strdup (const char *str)
254 {
255 asm ("");
256 if (*str != 'f')
257 __builtin_abort ();
258 good2++;
259 return strdupped_user;
260 }
261
262 __attribute__((__noclone__, __noinline__))
g_free(void * mem)263 void g_free (void * mem)
264 {
265 (void)mem;
266 asm ("");
267 __builtin_abort ();
268 }
269
270 struct user_info me = { .name = "me", .no_groups = 1, .groups = {42}, .next = 0};
271 struct user_info you = { .name = "you", .next = &me};
272 struct realm_group xgroups = { .name = "*", .id = 42, .next = 0};
273
main(void)274 int main(void)
275 {
276 char *orig_user = "?";
277 struct realm r = { .name = "x", .space = "space?", .groups = &xgroups, .next = 0};
278 request req = { .user = orig_user, .realm = "!", .authent = "z",
279 .internal_realm = axis_realm};
280 realms = &r;
281 users = &you;
282 if (authent_author (&req) != 0 || good0 != 1 || good1 != 1 || good2 != 1
283 || req.user != orig_user
284 || req.internal_realm != axis_realm)
285 __builtin_abort ();
286 __builtin_exit (0);
287 }
288
289