Commit ab98c236 authored by Niels Möller's avatar Niels Möller
Browse files

Bug fixes. New convention for return values from the AUTHENTICATE-method.

Rev: src/server_userauth.c:1.4
parent b1249ec5
...@@ -2,15 +2,21 @@ ...@@ -2,15 +2,21 @@
* *
* Server side user authentication. */ * Server side user authentication. */
#include "service.h"
#include "userauth.h" #include "userauth.h"
#include "format.h"
#include "service.h"
#include "ssh.h"
#include "xalloc.h"
#include <assert.h>
/* FIXME: Supports only password authentication so far. There should /* FIXME: Supports only password authentication so far. There should
* be some abstraction for handling several authentication methods. */ * be some abstraction for handling several authentication methods. */
struct userauth_service struct userauth_service
{ {
struct service super; struct ssh_service super;
struct alist *methods; /* Maps authentication method names to methods */ struct alist *methods; /* Maps authentication method names to methods */
}; };
...@@ -40,17 +46,20 @@ struct lsh_string *format_userauth_failure(int *methods, int partial) ...@@ -40,17 +46,20 @@ struct lsh_string *format_userauth_failure(int *methods, int partial)
return ssh_format("%c%A%c", SSH_MSG_USERAUTH_FAILURE, methods, partial); return ssh_format("%c%A%c", SSH_MSG_USERAUTH_FAILURE, methods, partial);
} }
struct lsh_string *format_userauth_success() struct lsh_string *format_userauth_success(void)
{ {
return ssh_format("%c", SSH_MSG_USERAUTH_SUCCESS); return ssh_format("%c", SSH_MSG_USERAUTH_SUCCESS);
} }
/* FIXME: Perhaps this should use a two-dimensional lookup, and call
* an authentication object depending on both service and method? */
/* NOTE: This implementation does not use any partial successes. As /* NOTE: This implementation does not use any partial successes. As
* soon as one authentication request is successful, the * soon as one authentication request is successful, the
* entire authentication process succeeds. */ * entire authentication process succeeds. */
static int do_handle_user_auth(struct packet_handler *c, static int do_handle_userauth(struct packet_handler *c,
struct ssh_connection *connection, struct ssh_connection *connection,
struct lsh_string *packet) struct lsh_string *packet)
{ {
struct userauth_handler * closure = (struct userauth_handler *) c; struct userauth_handler * closure = (struct userauth_handler *) c;
struct simple_buffer buffer; struct simple_buffer buffer;
...@@ -59,59 +68,74 @@ static int do_handle_user_auth(struct packet_handler *c, ...@@ -59,59 +68,74 @@ static int do_handle_user_auth(struct packet_handler *c,
struct lsh_string *user; struct lsh_string *user;
int requested_service; int requested_service;
int method; int method;
int res;
MDEBUG(closure); MDEBUG(closure);
simple_buffer_init(&buffer, packet->length, packet->data); simple_buffer_init(&buffer, packet->length, packet->data);
if (parse_uint8(&buffer, &msg_number) if (parse_uint8(&buffer, &msg_number)
&& (msg_number == SSH_MSG_USERAUTH_REQUEST) && (msg_number == SSH_MSG_USERAUTH_REQUEST)
&& parse_string_copy(&buffer, &user) && ( (user = parse_string_copy(&buffer)) )
&& parse_atom(&buffer, &requested_service) && parse_atom(&buffer, &requested_service)
&& parse_atom(&buffer, &method)) && parse_atom(&buffer, &method))
{ {
struct ssh_service *service; struct ssh_service *service;
self->attempts--; struct userauth *auth;
closure->attempts--;
struct userauth *auth = ALIST_GET(closure->methods, method); auth = ALIST_GET(closure->methods, method);
if (!auth) if (!auth)
return attempts return closure->attempts
? A_WRITE(connection->write, ? A_WRITE(connection->write,
format_userauth_failure(self->advertised_methods, format_userauth_failure(closure->advertised_methods,
0)) 0))
: LSH_FAIL | LSH_DIE; : LSH_FAIL | LSH_DIE;
res = AUTHENTICATE(auth, user, requested_service,
&buffer, &service);
if (LSH_CLOSEDP(res))
return res;
if (AUTHENTICATE(auth, user, requested_service, if (res & LSH_AUTH_FAILED)
&buffer, &service))
{ {
if (service return res
&& SERVICE_INIT(service, connection)) | (closure->attempts
{ /* Access granted */ ? A_WRITE(connection->write,
/* Ignore any further userauth messages. */ format_userauth_failure(closure->advertised_methods,
connection->dispatch[SSH_MSG_USERAUTH_REQUEST] 0))
= connection->ignore; /* FIXME: Send a disconnect message */
return A_WRITE(connection->write, format_userauth_success()); : LSH_FAIL | LSH_DIE);
}
else
return attempts
? A_WRITE(connection->write,
format_userauth_failure(self->advertised_methods,
0))
: LSH_FAIL | LSH_DIE;
} }
assert(service);
/* Access granted */
/* Ignore any further userauth messages. */
connection->dispatch[SSH_MSG_USERAUTH_REQUEST]
= connection->ignore;
res |= A_WRITE(connection->write, format_userauth_success());
if (LSH_CLOSEDP(res))
return res;
return res | SERVICE_INIT(service, connection);
} }
/* Invalid request */ /* Invalid request */
return LSH_FAIL | LSH_DIE; return LSH_FAIL | LSH_DIE;
} }
static int init_userauth(struct service *s, /* int name, */ static int init_userauth(struct ssh_service *s, /* int name, */
struct ssh_connection *c) struct ssh_connection *c)
{ {
struct userauth_service *self = (struct userauth_service *) s; struct userauth_service *self = (struct userauth_service *) s;
struct userauth_handler *auth; = xalloc(sizeof(struct userauth_handler)); struct userauth_handler *auth;
MDEBUG(self); MDEBUG(self);
NEW(auth);
auth->super.handler = do_handle_userauth; auth->super.handler = do_handle_userauth;
auth->methods = self->methods; auth->methods = self->methods;
auth->attempts = AUTH_ATTEMPTS; auth->attempts = AUTH_ATTEMPTS;
...@@ -123,11 +147,14 @@ static int init_userauth(struct service *s, /* int name, */ ...@@ -123,11 +147,14 @@ static int init_userauth(struct service *s, /* int name, */
struct ssh_service *make_userauth_service(struct alist *methods) struct ssh_service *make_userauth_service(struct alist *methods)
{ {
struct userauth_service *self = xalloc(sizeof(struct userauth_service)); struct userauth_service *self;
NEW(self);
self->super.init = init_userauth; self->super.init = init_userauth;
self->methods = methods; self->methods = methods;
return &self->super; return &self->super;
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment