diff options
Diffstat (limited to 'doc/examples/basicauthentication.c')
-rw-r--r-- | doc/examples/basicauthentication.c | 179 |
1 files changed, 36 insertions, 143 deletions
diff --git a/doc/examples/basicauthentication.c b/doc/examples/basicauthentication.c index 389242da..0b5ce62c 100644 --- a/doc/examples/basicauthentication.c +++ b/doc/examples/basicauthentication.c | |||
@@ -3,108 +3,12 @@ | |||
3 | #include <sys/socket.h> | 3 | #include <sys/socket.h> |
4 | #include <microhttpd.h> | 4 | #include <microhttpd.h> |
5 | #include <time.h> | 5 | #include <time.h> |
6 | #include <string.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <stdio.h> | ||
6 | 9 | ||
7 | #define PORT 8888 | 10 | #define PORT 8888 |
8 | 11 | ||
9 | #define REALM "\"Maintenance\"" | ||
10 | #define USER "a legitimate user" | ||
11 | #define PASSWORD "and his password" | ||
12 | |||
13 | |||
14 | char *string_to_base64 (const char *message); | ||
15 | |||
16 | |||
17 | static int | ||
18 | ask_for_authentication (struct MHD_Connection *connection, const char *realm) | ||
19 | { | ||
20 | int ret; | ||
21 | struct MHD_Response *response; | ||
22 | char *headervalue; | ||
23 | const char *strbase = "Basic realm="; | ||
24 | |||
25 | response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO); | ||
26 | if (!response) | ||
27 | return MHD_NO; | ||
28 | |||
29 | headervalue = malloc (strlen (strbase) + strlen (realm) + 1); | ||
30 | if (!headervalue) | ||
31 | return MHD_NO; | ||
32 | |||
33 | strcpy (headervalue, strbase); | ||
34 | strcat (headervalue, realm); | ||
35 | |||
36 | ret = MHD_add_response_header (response, "WWW-Authenticate", headervalue); | ||
37 | free (headervalue); | ||
38 | if (!ret) | ||
39 | { | ||
40 | MHD_destroy_response (response); | ||
41 | return MHD_NO; | ||
42 | } | ||
43 | |||
44 | ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response); | ||
45 | |||
46 | MHD_destroy_response (response); | ||
47 | |||
48 | return ret; | ||
49 | } | ||
50 | |||
51 | static int | ||
52 | is_authenticated (struct MHD_Connection *connection, | ||
53 | const char *username, const char *password) | ||
54 | { | ||
55 | const char *headervalue; | ||
56 | char *expected_b64, *expected; | ||
57 | const char *strbase = "Basic "; | ||
58 | int authenticated; | ||
59 | |||
60 | headervalue = | ||
61 | MHD_lookup_connection_value (connection, MHD_HEADER_KIND, | ||
62 | "Authorization"); | ||
63 | if (NULL == headervalue) | ||
64 | return 0; | ||
65 | if (0 != strncmp (headervalue, strbase, strlen (strbase))) | ||
66 | return 0; | ||
67 | |||
68 | expected = malloc (strlen (username) + 1 + strlen (password) + 1); | ||
69 | if (NULL == expected) | ||
70 | return 0; | ||
71 | |||
72 | strcpy (expected, username); | ||
73 | strcat (expected, ":"); | ||
74 | strcat (expected, password); | ||
75 | |||
76 | expected_b64 = string_to_base64 (expected); | ||
77 | free (expected); | ||
78 | if (NULL == expected_b64) | ||
79 | return 0; | ||
80 | |||
81 | authenticated = | ||
82 | (strcmp (headervalue + strlen (strbase), expected_b64) == 0); | ||
83 | |||
84 | free (expected_b64); | ||
85 | return authenticated; | ||
86 | } | ||
87 | |||
88 | |||
89 | static int | ||
90 | secret_page (struct MHD_Connection *connection) | ||
91 | { | ||
92 | int ret; | ||
93 | struct MHD_Response *response; | ||
94 | const char *page = "<html><body>A secret.</body></html>"; | ||
95 | |||
96 | response = | ||
97 | MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO, | ||
98 | MHD_NO); | ||
99 | if (!response) | ||
100 | return MHD_NO; | ||
101 | |||
102 | ret = MHD_queue_response (connection, MHD_HTTP_OK, response); | ||
103 | MHD_destroy_response (response); | ||
104 | |||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | 12 | ||
109 | static int | 13 | static int |
110 | answer_to_connection (void *cls, struct MHD_Connection *connection, | 14 | answer_to_connection (void *cls, struct MHD_Connection *connection, |
@@ -112,6 +16,12 @@ answer_to_connection (void *cls, struct MHD_Connection *connection, | |||
112 | const char *version, const char *upload_data, | 16 | const char *version, const char *upload_data, |
113 | size_t *upload_data_size, void **con_cls) | 17 | size_t *upload_data_size, void **con_cls) |
114 | { | 18 | { |
19 | char *user; | ||
20 | char *pass; | ||
21 | int fail; | ||
22 | int ret; | ||
23 | struct MHD_Response *response; | ||
24 | |||
115 | if (0 != strcmp (method, "GET")) | 25 | if (0 != strcmp (method, "GET")) |
116 | return MHD_NO; | 26 | return MHD_NO; |
117 | if (NULL == *con_cls) | 27 | if (NULL == *con_cls) |
@@ -119,11 +29,33 @@ answer_to_connection (void *cls, struct MHD_Connection *connection, | |||
119 | *con_cls = connection; | 29 | *con_cls = connection; |
120 | return MHD_YES; | 30 | return MHD_YES; |
121 | } | 31 | } |
122 | 32 | pass = NULL; | |
123 | if (!is_authenticated (connection, USER, PASSWORD)) | 33 | user = MHD_basic_auth_get_username_password (connection, &pass); |
124 | return ask_for_authentication (connection, REALM); | 34 | fail = ( (user == NULL) || |
125 | 35 | (0 != strcmp (user, "root")) || | |
126 | return secret_page (connection); | 36 | (0 != strcmp (pass, "pa$$w0rd") ) ); |
37 | if (user != NULL) free (user); | ||
38 | if (pass != NULL) free (pass); | ||
39 | if (fail) | ||
40 | { | ||
41 | const char *page = "<html><body>Go away.</body></html>"; | ||
42 | response = | ||
43 | MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO, | ||
44 | MHD_NO); | ||
45 | ret = MHD_queue_basic_auth_fail_response (connection, | ||
46 | "my realm", | ||
47 | response); | ||
48 | } | ||
49 | else | ||
50 | { | ||
51 | const char *page = "<html><body>A secret.</body></html>"; | ||
52 | response = | ||
53 | MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO, | ||
54 | MHD_NO); | ||
55 | ret = MHD_queue_response (connection, MHD_HTTP_OK, response); | ||
56 | } | ||
57 | MHD_destroy_response (response); | ||
58 | return ret; | ||
127 | } | 59 | } |
128 | 60 | ||
129 | 61 | ||
@@ -142,42 +74,3 @@ main () | |||
142 | MHD_stop_daemon (daemon); | 74 | MHD_stop_daemon (daemon); |
143 | return 0; | 75 | return 0; |
144 | } | 76 | } |
145 | |||
146 | |||
147 | char * | ||
148 | string_to_base64 (const char *message) | ||
149 | { | ||
150 | const char *lookup = | ||
151 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
152 | unsigned long l; | ||
153 | int i; | ||
154 | char *tmp; | ||
155 | size_t length = strlen (message); | ||
156 | |||
157 | tmp = malloc (length * 2); | ||
158 | if (NULL == tmp) | ||
159 | return tmp; | ||
160 | |||
161 | tmp[0] = 0; | ||
162 | |||
163 | for (i = 0; i < length; i += 3) | ||
164 | { | ||
165 | l = (((unsigned long) message[i]) << 16) | ||
166 | | (((i + 1) < length) ? (((unsigned long) message[i + 1]) << 8) : 0) | ||
167 | | (((i + 2) < length) ? ((unsigned long) message[i + 2]) : 0); | ||
168 | |||
169 | |||
170 | strncat (tmp, &lookup[(l >> 18) & 0x3F], 1); | ||
171 | strncat (tmp, &lookup[(l >> 12) & 0x3F], 1); | ||
172 | |||
173 | if (i + 1 < length) | ||
174 | strncat (tmp, &lookup[(l >> 6) & 0x3F], 1); | ||
175 | if (i + 2 < length) | ||
176 | strncat (tmp, &lookup[l & 0x3F], 1); | ||
177 | } | ||
178 | |||
179 | if (length % 3) | ||
180 | strncat (tmp, "===", 3 - length % 3); | ||
181 | |||
182 | return tmp; | ||
183 | } | ||