]> err.no Git - sope/blob - sope-appserver/NGObjWeb/SoOFS/OFSHttpPasswd.m
removed svn:keywords property from all affected files because this has several illnes...
[sope] / sope-appserver / NGObjWeb / SoOFS / OFSHttpPasswd.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include "OFSHttpPasswd.h"
24 #include "SoHTTPAuthenticator.h"
25 #include "common.h"
26
27 #if defined (__APPLE__) || defined(__FreeBSD__)
28 #  include <unistd.h>
29 #else
30 #  if defined(__OpenBSD__)
31 #    include <des.h>
32 #  else
33 #    include <crypt.h>
34 #  endif
35 #endif
36
37 /*
38   Note: a user-folder is different to an authenticator (though a user
39   folder can be a authenticator itself) ! A user-folder manages the whole
40   user-database while an authenticator decodes HTTP authentication info,
41   checks a password against a user and retrieves only authentication related
42   information on a user.
43   
44   So: a user-folder is strongly related to an authenticator, but isn't
45   usually the actual authenticator object (which usually inherits from
46   SoHTTPAuthenticator).
47 */
48
49 // TODO: implement ...
50
51 @interface OFSHttpPasswdAuthenticator : SoHTTPAuthenticator
52 {
53   OFSHttpPasswd *passwd; /* non-retained */
54 }
55
56 - (id)initWithObject:(id)_obj;
57 - (void)detach;
58
59 @end
60
61 @implementation OFSHttpPasswd
62
63 static BOOL    debugOn     = NO;
64 static NSArray *plainRoles = nil;
65 static NSArray *rootRoles  = nil;
66
67 + (void)initialize {
68   if (plainRoles == nil) {
69     plainRoles = [[NSArray alloc] initWithObjects:
70                       SoRole_Authenticated, SoRole_Anonymous, nil];
71   }
72   if (rootRoles == nil) {
73     rootRoles = [[NSArray alloc] initWithObjects:
74                                    SoRole_Manager, SoRole_Authenticated, 
75                                    SoRole_Anonymous, nil];
76   }
77 }
78
79 - (void)dealloc {
80   [self->content release];
81   [self->authenticator detach];
82   [self->authenticator release];
83   [super dealloc];
84 }
85
86 - (id)authenticatorInContext:(id)_ctx {
87   if (self->authenticator == nil) {
88     self->authenticator = 
89       [[OFSHttpPasswdAuthenticator alloc] initWithObject:self];
90   }
91   return self->authenticator;
92 }
93
94 /* loading htpasswd */
95
96 - (NSException *)primaryLoad {
97   NSMutableDictionary *md;
98   NSString *s;
99   NSArray  *lines;
100   unsigned i, count;
101
102   [self->content release]; self->content = nil;
103   
104   s = [self contentAsString];
105   lines = [s componentsSeparatedByString:@"\n"];
106   count = [lines count];
107   md = [NSMutableDictionary dictionaryWithCapacity:(count + 1)];
108   
109   for (i = 0; i < count; i++) {
110     NSString *s;
111     NSRange  r;
112     NSString *login, *pwd;
113     
114     s = [lines objectAtIndex:i];
115     r = [s rangeOfString:@":"];
116     if (r.length == 0) continue;
117     
118     login = [s substringToIndex:r.location];
119     pwd   = [s substringFromIndex:(r.location + r.length)];
120     
121     [md setObject:pwd forKey:login];
122   }
123   self->content = [md copy];
124   return nil;
125 }
126
127 - (NSString *)cryptedPasswordForLogin:(NSString *)_login {
128   NSException *error;
129   
130   if ([_login length] < 1)
131     return nil;
132   if (self->content)
133     return [self->content objectForKey:_login];
134   
135   if ((error = [self primaryLoad]))
136     return nil;
137   
138   return [self->content objectForKey:_login];
139 }
140
141 /* authenticator implementation */
142
143 - (BOOL)checkLogin:(NSString *)_login password:(NSString *)_pwd {
144   NSString *cryptedPwd;
145   NSString *cpo;
146   const char *cp;
147   
148   if (debugOn)
149     [self debugWithFormat:@"check '%@' against pwd ...", _login];
150   
151   if ((cryptedPwd = [self cryptedPasswordForLogin:_login]) == nil) {
152     [self debugWithFormat:@"  user '%@' not available in htpasswd", _login];
153     return NO;
154   }
155   
156   if (debugOn)
157     [self debugWithFormat:@"  check crypted pwd of user '%@' ...", _login];
158   
159   // salt is user-pwd itself (crypt(pwd, cryptedpwd))
160   cp = crypt([_pwd cString], [cryptedPwd cString]);
161   cpo = cp ? [NSString stringWithCString:cp] : nil;
162   
163   return [cryptedPwd isEqualToString:cpo];
164 }
165
166 - (NSString *)authRealm {
167   return [(WOApplication *)[WOApplication application] name];
168 }
169
170 - (BOOL)isRootLogin:(NSString *)_login {
171   return [_login isEqualToString:@"root"];
172 }
173 - (NSArray *)rolesForLogin:(NSString *)_login {
174   return [self isRootLogin:_login] ? rootRoles : plainRoles;
175 }
176
177 /* debugging */
178
179 - (BOOL)isDebuggingEnabled {
180   return debugOn;
181 }
182
183 @end /* OFSHttpPasswd */
184
185 @implementation OFSHttpPasswdAuthenticator
186
187 - (id)initWithObject:(id)_obj {
188   NSAssert(_obj, @"missing htpasswd user folder in argument ...");
189   if ((self = [super init])) {
190     self->passwd = _obj;
191   }
192   return self;
193 }
194 - (id)init {
195   return [self initWithObject:nil];
196 }
197
198 - (void)detach {
199   self->passwd = nil;
200 }
201
202 /* implement using folder itself ... */
203
204 - (BOOL)checkLogin:(NSString *)_login password:(NSString *)_pwd {
205   return [self->passwd checkLogin:_login password:_pwd];
206 }
207
208 - (NSString *)authRealm {
209   return [self->passwd authRealm];
210 }
211
212 - (NSArray *)rolesForLogin:(NSString *)_login {
213   return [self->passwd rolesForLogin:_login];
214 }
215
216 /* debugging */
217
218 - (BOOL)isDebuggingEnabled {
219   return debugOn;
220 }
221
222 @end /* OFSHttpPasswdAuthenticator */