1 // AuthenticationServer.cpp
3 #include "AuthenticationServer.h"
8 #include <HashString.h>
9 #include <util/KMessage.h>
11 #include "AuthenticationPanel.h"
12 #include "AuthenticationServerDefs.h"
13 #include "DebugSupport.h"
14 #include "TaskManager.h"
18 class AuthenticationServer::Authentication
{
26 Authentication(const char* user
, const char* password
)
32 status_t
SetTo(const char* user
, const char* password
)
34 if (fUser
.SetTo(user
) && fPassword
.SetTo(password
))
41 return (fUser
.GetLength() > 0);
44 const char* GetUser() const
46 return fUser
.GetString();
49 const char* GetPassword() const
51 return fPassword
.GetString();
60 class AuthenticationServer::ServerKey
{
68 ServerKey(const char* context
, const char* server
)
74 ServerKey(const ServerKey
& other
)
75 : fContext(other
.fContext
),
76 fServer(other
.fServer
)
80 uint32
GetHashCode() const
82 return fContext
.GetHashCode() * 17 + fServer
.GetHashCode();
85 ServerKey
& operator=(const ServerKey
& other
)
87 fContext
= other
.fContext
;
88 fServer
= other
.fServer
;
92 bool operator==(const ServerKey
& other
) const
94 return (fContext
== other
.fContext
&& fServer
== other
.fServer
);
97 bool operator!=(const ServerKey
& other
) const
99 return !(*this == other
);
108 class AuthenticationServer::ServerEntry
{
111 : fDefaultAuthentication(),
112 fUseDefaultAuthentication(false)
118 // delete the authentications
119 for (AuthenticationMap::Iterator it
= fAuthentications
.GetIterator();
121 delete it
.Next().value
;
125 void SetUseDefaultAuthentication(bool useDefaultAuthentication
)
127 fUseDefaultAuthentication
= useDefaultAuthentication
;
130 bool UseDefaultAuthentication() const
132 return fUseDefaultAuthentication
;
135 status_t
SetDefaultAuthentication(const char* user
, const char* password
)
137 return fDefaultAuthentication
.SetTo(user
, password
);
140 const Authentication
& GetDefaultAuthentication() const
142 return fDefaultAuthentication
;
145 status_t
SetAuthentication(const char* share
, const char* user
,
146 const char* password
)
148 // check, if an entry already exists for the share -- if it does,
150 Authentication
* authentication
= fAuthentications
.Get(share
);
152 return authentication
->SetTo(user
, password
);
153 // the entry does not exist yet: create and add a new one
154 authentication
= new(std::nothrow
) Authentication
;
157 status_t error
= authentication
->SetTo(user
, password
);
159 error
= fAuthentications
.Put(share
, authentication
);
161 delete authentication
;
165 Authentication
* GetAuthentication(const char* share
) const
167 return fAuthentications
.Get(share
);
171 typedef HashMap
<HashString
, Authentication
*> AuthenticationMap
;
173 Authentication fDefaultAuthentication
;
174 bool fUseDefaultAuthentication
;
175 AuthenticationMap fAuthentications
;
179 struct AuthenticationServer::ServerEntryMap
180 : HashMap
<ServerKey
, ServerEntry
*> {
184 class AuthenticationServer::UserDialogTask
: public Task
{
186 UserDialogTask(AuthenticationServer
* authenticationServer
,
187 const char* context
, const char* server
, const char* share
,
188 bool badPassword
, port_id replyPort
,
190 : Task("user dialog task"),
191 fAuthenticationServer(authenticationServer
),
195 fBadPassword(badPassword
),
196 fReplyPort(replyPort
),
197 fReplyToken(replyToken
),
202 virtual status_t
Execute()
205 char user
[B_OS_NAME_LENGTH
];
206 char password
[B_OS_NAME_LENGTH
];
208 fPanel
= new(std::nothrow
) AuthenticationPanel();
209 status_t error
= (fPanel
? B_OK
: B_NO_MEMORY
);
210 bool cancelled
= false;
211 HashString defaultUser
;
212 HashString defaultPassword
;
213 fAuthenticationServer
->_GetAuthentication(fContext
.GetString(),
214 fServer
.GetString(), NULL
, &defaultUser
, &defaultPassword
);
216 cancelled
= fPanel
->GetAuthentication(fServer
.GetString(),
217 fShare
.GetString(), defaultUser
.GetString(),
218 defaultPassword
.GetString(), false, fBadPassword
, user
,
224 fAuthenticationServer
->_SendRequestReply(fReplyPort
, fReplyToken
,
225 error
, true, NULL
, NULL
);
226 } else if (cancelled
) {
227 fAuthenticationServer
->_SendRequestReply(fReplyPort
, fReplyToken
,
228 B_OK
, true, NULL
, NULL
);
230 fAuthenticationServer
->_AddAuthentication(fContext
.GetString(),
231 fServer
.GetString(), fShare
.GetString(), user
, password
,
233 fAuthenticationServer
->_SendRequestReply(fReplyPort
, fReplyToken
,
234 B_OK
, false, user
, password
);
246 AuthenticationServer
* fAuthenticationServer
;
253 AuthenticationPanel
* fPanel
;
258 AuthenticationServer::AuthenticationServer()
260 BApplication("application/x-vnd.haiku-authentication_server"),
264 fServerEntries(NULL
),
270 AuthenticationServer::~AuthenticationServer()
273 // terminate the request thread
274 if (fRequestPort
>= 0)
275 delete_port(fRequestPort
);
276 if (fRequestThread
>= 0) {
278 wait_for_thread(fRequestPort
, &result
);
280 // delete the server entries
281 for (ServerEntryMap::Iterator it
= fServerEntries
->GetIterator();
283 delete it
.Next().value
;
289 AuthenticationServer::Init()
291 // create the server entry map
292 fServerEntries
= new(std::nothrow
) ServerEntryMap
;
295 status_t error
= fServerEntries
->InitCheck();
298 // create the request port
299 fRequestPort
= create_port(10, kAuthenticationServerPortName
);
300 if (fRequestPort
< 0)
302 // spawn the request thread
303 fRequestThread
= spawn_thread(&_RequestThreadEntry
, "request thread",
304 B_NORMAL_PRIORITY
, this);
305 if (fRequestThread
< 0)
306 return fRequestThread
;
307 resume_thread(fRequestThread
);
311 // _RequestThreadEntry
313 AuthenticationServer::_RequestThreadEntry(void* data
)
315 return ((AuthenticationServer
*)data
)->_RequestThread();
320 AuthenticationServer::_RequestThread()
322 TaskManager taskManager
;
323 while (!fTerminating
) {
324 taskManager
.RemoveDoneTasks();
327 status_t error
= request
.ReceiveFrom(fRequestPort
);
330 // get the parameters
331 const char* context
= NULL
;
332 const char* server
= NULL
;
333 const char* share
= NULL
;
334 bool badPassword
= true;
335 request
.FindString("context", &context
);
336 request
.FindString("server", &server
);
337 request
.FindString("share", &share
);
338 request
.FindBool("badPassword", &badPassword
);
339 if (!context
|| !server
|| !share
)
341 HashString foundUser
;
342 HashString foundPassword
;
343 if (!badPassword
&& _GetAuthentication(context
, server
, share
,
344 &foundUser
, &foundPassword
)) {
345 _SendRequestReply(request
.ReplyPort(), request
.ReplyToken(),
346 error
, false, foundUser
.GetString(), foundPassword
.GetString());
348 // we need to ask the user: create a task that does it
349 UserDialogTask
* task
= new(std::nothrow
) UserDialogTask(this,
350 context
, server
, share
, badPassword
, request
.ReplyPort(),
351 request
.ReplyToken());
353 ERROR("AuthenticationServer::_RequestThread(): ERROR: "
354 "failed to allocate ");
357 status_t error
= taskManager
.RunTask(task
);
359 ERROR("AuthenticationServer::_RequestThread(): Failed to "
360 "start server info task: %s\n", strerror(error
));
368 // _GetAuthentication
370 If share is NULL, the default authentication for the server is returned.
373 AuthenticationServer::_GetAuthentication(const char* context
,
374 const char* server
, const char* share
, HashString
* user
,
375 HashString
* password
)
377 if (!context
|| !server
|| !user
|| !password
)
379 // get the server entry
380 AutoLocker
<BLocker
> _(fLock
);
381 ServerKey
key(context
, server
);
382 ServerEntry
* serverEntry
= fServerEntries
->Get(key
);
385 // get the authentication
386 const Authentication
* authentication
= NULL
;
388 serverEntry
->GetAuthentication(share
);
389 if (!authentication
&& serverEntry
->UseDefaultAuthentication())
390 authentication
= &serverEntry
->GetDefaultAuthentication();
392 authentication
= &serverEntry
->GetDefaultAuthentication();
393 if (!authentication
|| !authentication
->IsValid())
395 return (user
->SetTo(authentication
->GetUser())
396 && password
->SetTo(authentication
->GetPassword()));
399 // _AddAuthentication
401 AuthenticationServer::_AddAuthentication(const char* context
,
402 const char* server
, const char* share
, const char* user
,
403 const char* password
, bool makeDefault
)
405 AutoLocker
<BLocker
> _(fLock
);
406 ServerKey
key(context
, server
);
407 // get the server entry
408 ServerEntry
* serverEntry
= fServerEntries
->Get(key
);
410 // server entry does not exist yet: create a new one
411 serverEntry
= new(std::nothrow
) ServerEntry
;
414 status_t error
= fServerEntries
->Put(key
, serverEntry
);
420 // put the authentication
421 status_t error
= serverEntry
->SetAuthentication(share
, user
, password
);
423 if (makeDefault
|| !serverEntry
->UseDefaultAuthentication())
424 serverEntry
->SetDefaultAuthentication(user
, password
);
426 serverEntry
->SetUseDefaultAuthentication(true);
433 AuthenticationServer::_SendRequestReply(port_id port
, int32 token
,
434 status_t error
, bool cancelled
, const char* user
, const char* password
)
438 reply
.AddInt32("error", error
);
440 reply
.AddBool("cancelled", cancelled
);
442 reply
.AddString("user", user
);
443 reply
.AddString("password", password
);
447 return reply
.SendTo(port
, token
);
455 AuthenticationServer app
;
456 status_t error
= app
.Init();