1 | /* |
---|
2 | * security.c -- Security handler |
---|
3 | * |
---|
4 | * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. |
---|
5 | * |
---|
6 | * See the file "license.txt" for usage and redistribution license requirements |
---|
7 | */ |
---|
8 | |
---|
9 | /******************************** Description *********************************/ |
---|
10 | |
---|
11 | /* |
---|
12 | * This module provides a basic security policy. |
---|
13 | */ |
---|
14 | |
---|
15 | /********************************* Includes ***********************************/ |
---|
16 | |
---|
17 | #include "wsIntrn.h" |
---|
18 | #include "um.h" |
---|
19 | #ifdef DIGEST_ACCESS_SUPPORT |
---|
20 | #include "websda.h" |
---|
21 | #endif |
---|
22 | |
---|
23 | /********************************** Defines ***********************************/ |
---|
24 | /* |
---|
25 | * The following #defines change the behaviour of security in the absence |
---|
26 | * of User Management. |
---|
27 | * Note that use of User management functions require prior calling of |
---|
28 | * umInit() to behave correctly |
---|
29 | */ |
---|
30 | |
---|
31 | #ifndef USER_MANAGEMENT_SUPPORT |
---|
32 | #define umGetAccessMethodForURL(url) AM_FULL |
---|
33 | #define umUserExists(userid) 0 |
---|
34 | #define umUserCanAccessURL(userid, url) 1 |
---|
35 | #define umGetUserPassword(userid) websGetPassword() |
---|
36 | #define umGetAccessLimitSecure(accessLimit) 0 |
---|
37 | #define umGetAccessLimit(url) NULL |
---|
38 | #endif |
---|
39 | |
---|
40 | /******************************** Local Data **********************************/ |
---|
41 | |
---|
42 | static char_t websPassword[WEBS_MAX_PASS]; /* Access password (decoded) */ |
---|
43 | #ifdef _DEBUG |
---|
44 | static int debugSecurity = 1; |
---|
45 | #else |
---|
46 | static int debugSecurity = 0; |
---|
47 | #endif |
---|
48 | |
---|
49 | /*********************************** Code *************************************/ |
---|
50 | /* |
---|
51 | * Determine if this request should be honored |
---|
52 | */ |
---|
53 | |
---|
54 | int websSecurityHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg, |
---|
55 | char_t *url, char_t *path, char_t *query) |
---|
56 | { |
---|
57 | char_t *type, *userid, *password, *accessLimit; |
---|
58 | int flags, nRet; |
---|
59 | accessMeth_t am; |
---|
60 | |
---|
61 | a_assert(websValid(wp)); |
---|
62 | a_assert(url && *url); |
---|
63 | a_assert(path && *path); |
---|
64 | /* |
---|
65 | * Get the critical request details |
---|
66 | */ |
---|
67 | type = websGetRequestType(wp); |
---|
68 | password = websGetRequestPassword(wp); |
---|
69 | userid = websGetRequestUserName(wp); |
---|
70 | flags = websGetRequestFlags(wp); |
---|
71 | /* |
---|
72 | * Get the access limit for the URL. Exit if none found. |
---|
73 | */ |
---|
74 | accessLimit = umGetAccessLimit(path); |
---|
75 | if (accessLimit == NULL) { |
---|
76 | return 0; |
---|
77 | } |
---|
78 | |
---|
79 | /* |
---|
80 | * Check to see if URL must be encrypted |
---|
81 | */ |
---|
82 | #ifdef WEBS_SSL_SUPPORT |
---|
83 | nRet = umGetAccessLimitSecure(accessLimit); |
---|
84 | if (nRet && ((flags | WEBS_SECURE) == 0)) { |
---|
85 | websStats.access++; |
---|
86 | websError(wp, 200, T("Access Denied\nSecure access is required.")); |
---|
87 | trace(3, T("SEC: Non-secure access attempted on <%s>\n"), path); |
---|
88 | return 1; |
---|
89 | } |
---|
90 | #endif |
---|
91 | |
---|
92 | /* |
---|
93 | * Get the access limit for the URL |
---|
94 | */ |
---|
95 | am = umGetAccessMethodForURL(accessLimit); |
---|
96 | |
---|
97 | nRet = 0; |
---|
98 | if ((flags & WEBS_LOCAL_REQUEST) && (debugSecurity == 0)) { |
---|
99 | /* |
---|
100 | * Local access is always allowed (defeat when debugging) |
---|
101 | */ |
---|
102 | } else if (am == AM_NONE) { |
---|
103 | /* |
---|
104 | * URL is supposed to be hidden! Make like it wasn't found. |
---|
105 | */ |
---|
106 | websStats.access++; |
---|
107 | websError(wp, 400, T("Page Not Found")); |
---|
108 | nRet = 1; |
---|
109 | } else if (userid && *userid) { |
---|
110 | if (!umUserExists(userid)) { |
---|
111 | websStats.access++; |
---|
112 | websError(wp, 200, T("Access Denied\nUnknown User")); |
---|
113 | trace(3, T("SEC: Unknown user <%s> attempted to access <%s>\n"), |
---|
114 | userid, path); |
---|
115 | nRet = 1; |
---|
116 | } else if (!umUserCanAccessURL(userid, accessLimit)) { |
---|
117 | websStats.access++; |
---|
118 | websError(wp, 403, T("Access Denied\nProhibited User")); |
---|
119 | nRet = 1; |
---|
120 | } else if (password && * password) { |
---|
121 | char_t * userpass = umGetUserPassword(userid); |
---|
122 | if (userpass) { |
---|
123 | if (gstrcmp(password, userpass) != 0) { |
---|
124 | websStats.access++; |
---|
125 | websError(wp, 200, T("Access Denied\nWrong Password")); |
---|
126 | trace(3, T("SEC: Password fail for user <%s>") |
---|
127 | T("attempt to access <%s>\n"), userid, path); |
---|
128 | nRet = 1; |
---|
129 | } else { |
---|
130 | /* |
---|
131 | * User and password check out. |
---|
132 | */ |
---|
133 | } |
---|
134 | |
---|
135 | bfree (B_L, userpass); |
---|
136 | } |
---|
137 | #ifdef DIGEST_ACCESS_SUPPORT |
---|
138 | } else if (flags & WEBS_AUTH_DIGEST) { |
---|
139 | |
---|
140 | char_t *digestCalc; |
---|
141 | |
---|
142 | /* |
---|
143 | * Check digest for equivalence |
---|
144 | */ |
---|
145 | wp->password = umGetUserPassword(userid); |
---|
146 | |
---|
147 | a_assert(wp->digest); |
---|
148 | a_assert(wp->nonce); |
---|
149 | a_assert(wp->password); |
---|
150 | |
---|
151 | digestCalc = websCalcDigest(wp); |
---|
152 | a_assert(digestCalc); |
---|
153 | |
---|
154 | if (gstrcmp(wp->digest, digestCalc) != 0) { |
---|
155 | websStats.access++; |
---|
156 | websError(wp, 200, T("Access Denied\nWrong Password")); |
---|
157 | nRet = 1; |
---|
158 | } |
---|
159 | |
---|
160 | bfree (B_L, digestCalc); |
---|
161 | #endif |
---|
162 | } else { |
---|
163 | /* |
---|
164 | * No password has been specified |
---|
165 | */ |
---|
166 | #ifdef DIGEST_ACCESS_SUPPORT |
---|
167 | if (am == AM_DIGEST) { |
---|
168 | wp->flags |= WEBS_AUTH_DIGEST; |
---|
169 | } |
---|
170 | #endif |
---|
171 | websStats.errors++; |
---|
172 | websError(wp, 401, |
---|
173 | T("Access to this document requires a password")); |
---|
174 | nRet = 1; |
---|
175 | } |
---|
176 | } else if (am != AM_FULL) { |
---|
177 | /* |
---|
178 | * This will cause the browser to display a password / username |
---|
179 | * dialog |
---|
180 | */ |
---|
181 | #ifdef DIGEST_ACCESS_SUPPORT |
---|
182 | if (am == AM_DIGEST) { |
---|
183 | wp->flags |= WEBS_AUTH_DIGEST; |
---|
184 | } |
---|
185 | #endif |
---|
186 | websStats.errors++; |
---|
187 | websError(wp, 401, T("Access to this document requires a User ID")); |
---|
188 | nRet = 1; |
---|
189 | } |
---|
190 | |
---|
191 | bfree(B_L, accessLimit); |
---|
192 | |
---|
193 | return nRet; |
---|
194 | } |
---|
195 | |
---|
196 | /******************************************************************************/ |
---|
197 | /* |
---|
198 | * Delete the default security handler |
---|
199 | */ |
---|
200 | |
---|
201 | void websSecurityDelete() |
---|
202 | { |
---|
203 | websUrlHandlerDelete(websSecurityHandler); |
---|
204 | } |
---|
205 | |
---|
206 | /******************************************************************************/ |
---|
207 | /* |
---|
208 | * Store the new password, expect a decoded password. Store in websPassword in |
---|
209 | * the decoded form. |
---|
210 | */ |
---|
211 | |
---|
212 | void websSetPassword(char_t *password) |
---|
213 | { |
---|
214 | a_assert(password); |
---|
215 | |
---|
216 | gstrncpy(websPassword, password, TSZ(websPassword)); |
---|
217 | } |
---|
218 | |
---|
219 | /******************************************************************************/ |
---|
220 | /* |
---|
221 | * Get password, return the decoded form |
---|
222 | */ |
---|
223 | |
---|
224 | char_t *websGetPassword() |
---|
225 | { |
---|
226 | return bstrdup(B_L, websPassword); |
---|
227 | } |
---|
228 | |
---|
229 | /******************************************************************************/ |
---|
230 | |
---|