]> err.no Git - sope/blob - sope-appserver/SoOFS/OFSHttpPasswd.m
added strict OSX bundle dependencies
[sope] / sope-appserver / SoOFS / OFSHttpPasswd.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE 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   SOPE 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 SOPE; 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
22 #include "OFSHttpPasswd.h"
23 #include <SoObjects/SoHTTPAuthenticator.h>
24 #include "common.h"
25
26 #if defined (__APPLE__) || defined(__FreeBSD__)
27 #  include <unistd.h>
28 #else
29 #  if defined(__OpenBSD__)
30 #    include <des.h>
31 #  else
32 #    include <crypt.h>
33 #  endif
34 #endif
35
36 /*
37   Note: a user-folder is different to an authenticator (though a user
38   folder can be a authenticator itself) ! A user-folder manages the whole
39   user-database while an authenticator decodes HTTP authentication info,
40   checks a password against a user and retrieves only authentication related
41   information on a user.
42   
43   So: a user-folder is strongly related to an authenticator, but isn't
44   usually the actual authenticator object (which usually inherits from
45   SoHTTPAuthenticator).
46 */
47
48 // TODO: implement ...
49
50 @interface OFSHttpPasswdAuthenticator : SoHTTPAuthenticator
51 {
52   OFSHttpPasswd *passwd; /* non-retained */
53 }
54
55 - (id)initWithObject:(id)_obj;
56 - (void)detach;
57
58 @end
59
60 @implementation OFSHttpPasswd
61
62 static BOOL    debugOn     = NO;
63 static NSArray *plainRoles = nil;
64 static NSArray *rootRoles  = nil;
65
66 + (void)initialize {
67   if (plainRoles == nil) {
68     plainRoles = [[NSArray alloc] initWithObjects:
69                       SoRole_Authenticated, SoRole_Anonymous, nil];
70   }
71   if (rootRoles == nil) {
72     rootRoles = [[NSArray alloc] initWithObjects:
73                                    SoRole_Manager, SoRole_Authenticated, 
74                                    SoRole_Anonymous, nil];
75   }
76 }
77
78 - (void)dealloc {
79   [self->content release];
80   [self->authenticator detach];
81   [self->authenticator release];
82   [super dealloc];
83 }
84
85 - (id)authenticatorInContext:(id)_ctx {
86   if (self->authenticator == nil) {
87     self->authenticator = 
88       [[OFSHttpPasswdAuthenticator alloc] initWithObject:self];
89   }
90   return self->authenticator;
91 }
92
93 /* loading htpasswd */
94
95 - (NSException *)primaryLoad {
96   NSMutableDictionary *md;
97   NSString *s;
98   NSArray  *lines;
99   unsigned i, count;
100
101   [self->content release]; self->content = nil;
102   
103   s = [self contentAsString];
104   lines = [s componentsSeparatedByString:@"\n"];
105   count = [lines count];
106   md = [NSMutableDictionary dictionaryWithCapacity:(count + 1)];
107   
108   for (i = 0; i < count; i++) {
109     NSString *s;
110     NSRange  r;
111     NSString *login, *pwd;
112     
113     s = [lines objectAtIndex:i];
114     r = [s rangeOfString:@":"];
115     if (r.length == 0) continue;
116     
117     login = [s substringToIndex:r.location];
118     pwd   = [s substringFromIndex:(r.location + r.length)];
119     
120     [md setObject:pwd forKey:login];
121   }
122   self->content = [md copy];
123   return nil;
124 }
125
126 - (NSString *)cryptedPasswordForLogin:(NSString *)_login {
127   NSException *error;
128   
129   if ([_login length] < 1)
130     return nil;
131   if (self->content)
132     return [self->content objectForKey:_login];
133   
134   if ((error = [self primaryLoad]))
135     return nil;
136   
137   return [self->content objectForKey:_login];
138 }
139
140 /* authenticator implementation */
141
142 - (BOOL)checkLogin:(NSString *)_login password:(NSString *)_pwd {
143   NSString *cryptedPwd;
144   NSString *cpo;
145   const char *cp;
146   
147   if (debugOn)
148     [self debugWithFormat:@"check '%@' against pwd ...", _login];
149   
150   if ((cryptedPwd = [self cryptedPasswordForLogin:_login]) == nil) {
151     [self debugWithFormat:@"  user '%@' not available in htpasswd", _login];
152     return NO;
153   }
154   
155   if (debugOn)
156     [self debugWithFormat:@"  check crypted pwd of user '%@' ...", _login];
157   
158   // salt is user-pwd itself (crypt(pwd, cryptedpwd))
159   cp = crypt([_pwd cString], [cryptedPwd cString]);
160   cpo = cp ? [NSString stringWithCString:cp] : nil;
161   
162   return [cryptedPwd isEqualToString:cpo];
163 }
164
165 - (NSString *)authRealm {
166   return [(WOApplication *)[WOApplication application] name];
167 }
168
169 - (BOOL)isRootLogin:(NSString *)_login {
170   return [_login isEqualToString:@"root"];
171 }
172 - (NSArray *)rolesForLogin:(NSString *)_login {
173   return [self isRootLogin:_login] ? rootRoles : plainRoles;
174 }
175
176 /* debugging */
177
178 - (BOOL)isDebuggingEnabled {
179   return debugOn;
180 }
181
182 @end /* OFSHttpPasswd */
183
184 @implementation OFSHttpPasswdAuthenticator
185
186 - (id)initWithObject:(id)_obj {
187   NSAssert(_obj, @"missing htpasswd user folder in argument ...");
188   if ((self = [super init])) {
189     self->passwd = _obj;
190   }
191   return self;
192 }
193 - (id)init {
194   return [self initWithObject:nil];
195 }
196
197 - (void)detach {
198   self->passwd = nil;
199 }
200
201 /* implement using folder itself ... */
202
203 - (BOOL)checkLogin:(NSString *)_login password:(NSString *)_pwd {
204   return [self->passwd checkLogin:_login password:_pwd];
205 }
206
207 - (NSString *)authRealm {
208   return [self->passwd authRealm];
209 }
210
211 - (NSArray *)rolesForLogin:(NSString *)_login {
212   return [self->passwd rolesForLogin:_login];
213 }
214
215 /* debugging */
216
217 - (BOOL)isDebuggingEnabled {
218   return debugOn;
219 }
220
221 @end /* OFSHttpPasswdAuthenticator */