diff options
Diffstat (limited to 'doc/examples/basicauthentication.c')
-rw-r--r-- | doc/examples/basicauthentication.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/doc/examples/basicauthentication.c b/doc/examples/basicauthentication.c new file mode 100644 index 00000000..eecaaf05 --- /dev/null +++ b/doc/examples/basicauthentication.c | |||
@@ -0,0 +1,152 @@ | |||
1 | #include <microhttpd.h> | ||
2 | #include <string.h> | ||
3 | #include <stdio.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <time.h> | ||
6 | |||
7 | #define PORT 8888 | ||
8 | |||
9 | #define REALM "\"Maintenance\"" | ||
10 | #define USER "a legitimate user" | ||
11 | #define PASSWORD "and his password" | ||
12 | |||
13 | |||
14 | char* StringToBase64(const char *message); | ||
15 | |||
16 | |||
17 | int AskForAuthentication(struct MHD_Connection *connection, const char *realm) | ||
18 | { | ||
19 | int ret; | ||
20 | struct MHD_Response *response; | ||
21 | char *headervalue; | ||
22 | const char *strbase = "Basic realm="; | ||
23 | |||
24 | response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_NO); | ||
25 | if (!response) return MHD_NO; | ||
26 | |||
27 | headervalue = malloc( strlen(strbase) + strlen(realm) + 1); | ||
28 | if (!headervalue) return MHD_NO; | ||
29 | |||
30 | strcpy(headervalue, strbase); | ||
31 | strcat(headervalue, realm); | ||
32 | |||
33 | ret = MHD_add_response_header(response, "WWW-Authenticate", headervalue); | ||
34 | free(headervalue); | ||
35 | if (!ret) {MHD_destroy_response (response); return MHD_NO;} | ||
36 | |||
37 | ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response); | ||
38 | |||
39 | MHD_destroy_response (response); | ||
40 | |||
41 | return ret; | ||
42 | } | ||
43 | |||
44 | int IsAuthenticated(struct MHD_Connection *connection, const char *username, | ||
45 | const char *password) | ||
46 | { | ||
47 | const char *headervalue; | ||
48 | char *expected_b64, *expected; | ||
49 | const char *strbase = "Basic "; | ||
50 | int authenticated; | ||
51 | |||
52 | headervalue = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Authorization"); | ||
53 | if(headervalue == NULL) return 0; | ||
54 | if (strncmp(headervalue, strbase, strlen(strbase))!=0) return 0; | ||
55 | |||
56 | expected = malloc(strlen(username) + 1 + strlen(password) + 1); | ||
57 | if(expected == NULL) return 0; | ||
58 | |||
59 | strcpy(expected, username); | ||
60 | strcat(expected, ":"); | ||
61 | strcat(expected, password); | ||
62 | |||
63 | expected_b64 = StringToBase64(expected); | ||
64 | if(expected_b64 == NULL) return 0; | ||
65 | |||
66 | strcpy(expected, strbase); | ||
67 | |||
68 | authenticated = (strcmp(headervalue+strlen(strbase), expected_b64) == 0); | ||
69 | |||
70 | free(expected_b64); | ||
71 | |||
72 | return authenticated; | ||
73 | } | ||
74 | |||
75 | |||
76 | int SecretPage(struct MHD_Connection *connection) | ||
77 | { | ||
78 | int ret; | ||
79 | struct MHD_Response *response; | ||
80 | const char *page = "<html><body>A secret.</body></html>"; | ||
81 | |||
82 | response = MHD_create_response_from_data(strlen(page), (void*)page, MHD_NO, MHD_NO); | ||
83 | if (!response) return MHD_NO; | ||
84 | |||
85 | ret = MHD_queue_response (connection, MHD_HTTP_OK, response); | ||
86 | |||
87 | MHD_destroy_response (response); | ||
88 | |||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | |||
93 | int AnswerToConnection(void *cls, struct MHD_Connection *connection, | ||
94 | const char *url, const char *method, const char *version, | ||
95 | const char *upload_data, unsigned int *upload_data_size, void **con_cls) | ||
96 | { | ||
97 | if (0 != strcmp(method, "GET")) return MHD_NO; | ||
98 | if(*con_cls==NULL) {*con_cls=connection; return MHD_YES;} | ||
99 | |||
100 | if (!IsAuthenticated(connection, USER, PASSWORD)) | ||
101 | return AskForAuthentication(connection, REALM); | ||
102 | |||
103 | return SecretPage(connection); | ||
104 | } | ||
105 | |||
106 | |||
107 | int main () | ||
108 | { | ||
109 | struct MHD_Daemon *daemon; | ||
110 | |||
111 | daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL, | ||
112 | &AnswerToConnection, NULL, MHD_OPTION_END); | ||
113 | |||
114 | if (daemon == NULL) return 1; | ||
115 | |||
116 | getchar(); | ||
117 | |||
118 | MHD_stop_daemon(daemon); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | |||
123 | char* StringToBase64(const char *message) | ||
124 | { | ||
125 | const char *lookup = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
126 | unsigned long l; | ||
127 | int i; | ||
128 | char *tmp; | ||
129 | size_t length = strlen(message); | ||
130 | |||
131 | tmp = malloc(length*2); | ||
132 | if (tmp==NULL) return tmp; | ||
133 | tmp[0]=0; | ||
134 | |||
135 | for(i=0; i<length; i+=3) | ||
136 | { | ||
137 | l = ( ((unsigned long)message[i])<<16 ) | | ||
138 | (((i+1) < length) ? (((unsigned long)message[i+1])<<8 ) : 0 ) | | ||
139 | (((i+2) < length) ? ( (unsigned long)message[i+2] ) : 0 ); | ||
140 | |||
141 | |||
142 | strncat(tmp, &lookup[(l>>18) & 0x3F], 1); | ||
143 | strncat(tmp, &lookup[(l>>12) & 0x3F], 1); | ||
144 | |||
145 | if (i+1 < length) strncat(tmp, &lookup[(l>> 6) & 0x3F], 1); | ||
146 | if (i+2 < length) strncat(tmp, &lookup[(l ) & 0x3F], 1); | ||
147 | } | ||
148 | |||
149 | if (length%3) strncat(tmp, "===", 3-length%3) ; | ||
150 | |||
151 | return tmp; | ||
152 | } | ||