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

* src/server_userauth.c (userauth_handler): New attributes

service_e and auth_e. WE use different exception handlers when
invoking the AUTHENTICATE method and when invoking the service.
(do_userauth_continuation): Simplified this continuation. It is
passed a user, and returns the connection.
(do_handle_userauth): When a service is eventually invoked, it is
passed a single argument: the connection. Previously, the user
object was passed as argument to the service.
(do_userauth): Clear the user attribute of the connection, and
display a warning message if the connection was already
authenticated.
(do_userauth): Don't call make_userauth_continuation() here.

Rev: src/server_userauth.c:1.27
Rev: src/server_userauth.h:1.12
parent ee422628
......@@ -42,7 +42,7 @@
struct lsh_string *
format_userauth_failure(struct int_list *methods,
int partial)
int partial)
{
return ssh_format("%c%A%c", SSH_MSG_USERAUTH_FAILURE, methods, partial);
}
......@@ -71,24 +71,92 @@ format_userauth_success(void)
(name userauth_handler)
(super packet_handler)
(vars
; Attempts left
;; (attempts simple int)
; What to do after successful authentication
; What to do after successful authentication.
(c object command_continuation)
; or failed.
(e object exception_handler)
; Methods advertised in failure messages
;; (advertised_methods object int_list)
; Maps authentication methods to userath objects
; Handler to use when starting a new service.
(service_e object exception_handler)
; Handler to use when invoking an authentication method.
(auth_e object exception_handler)
; Maps authentication methods to userauth objects
(methods object alist)
; Maps services to commands
(services object alist)))
*/
/* FIXME: This code doesn't handle authentication methods where the
* result (continuation or exception) is not invoked immediately.
* There are two problems:
*
* 1. Requests are not necessarily replied to in order. That is bad,
* but can probably be fixed fairly easily the same way that it is
* done for GLOBAL_REQUEST messages.
*
* 2. Packets that are received after a sucessful USERAUTH_REQUEST
* message, but before it is processed and replied to, must somehow be
* queued until we know that the user is authenticated for some
* service to receive them.
*
* I think the right thing to do is to serialize userauth requests
* completely: if a request can't be replied to immediately, put the
* entire connection on hold until the reply is ready.
*
* This code now uses serialization, using connection_lock() and
* connection_unlock(). However, the implementation of serialization
* is rather stupid. And will crash if a userauth method returns to
* the main loop while the connection is still locked. */
/* GABA:
(class
(name userauth_continuation)
(super command_continuation)
(vars
(up object command_continuation)
(connection object ssh_connection)))
*/
static void
do_userauth_continuation(struct command_continuation *s,
struct lsh_object *a)
{
CAST(userauth_continuation, self, s);
CAST_SUBTYPE(lsh_user, user, a);
unsigned i;
/* Access granted. */
assert(user);
self->connection->user = user;
/* Unlock connection */
connection_unlock(self->connection);
C_WRITE(self->connection, format_userauth_success());
/* Ignore any further userauth messages. */
for (i = SSH_FIRST_USERAUTH_GENERIC; i < SSH_FIRST_CONNECTION_GENERIC; i++)
self->connection->dispatch[i] = self->connection->ignore;
COMMAND_RETURN(self->up, self->connection);
}
static struct command_continuation *
make_userauth_continuation(struct ssh_connection *connection,
struct command_continuation *c)
{
NEW(userauth_continuation, self);
self->super.c = do_userauth_continuation;
self->up = c;
self->connection = connection;
return &self->super;
}
/* FIXME: Perhaps this should use a two-dimensional lookup, and call
* an authentication object depending on both service and method? */
......@@ -96,11 +164,11 @@ format_userauth_success(void)
* soon as one authentication request is successful, the
* entire authentication process succeeds. */
static void
do_handle_userauth(struct packet_handler *c,
do_handle_userauth(struct packet_handler *s,
struct ssh_connection *connection,
struct lsh_string *packet)
{
CAST(userauth_handler, closure, c);
CAST(userauth_handler, self, s);
struct simple_buffer buffer;
unsigned msg_number;
......@@ -116,9 +184,9 @@ do_handle_userauth(struct packet_handler *c,
&& parse_atom(&buffer, &requested_service)
&& parse_atom(&buffer, &method))
{
CAST_SUBTYPE(userauth, auth, ALIST_GET(closure->methods, method));
CAST_SUBTYPE(userauth, auth, ALIST_GET(self->methods, method));
CAST_SUBTYPE(command, service,
ALIST_GET(closure->services, requested_service));
ALIST_GET(self->services, requested_service));
/* Serialize handling of userauth requests */
connection_lock(connection);
......@@ -129,14 +197,15 @@ do_handle_userauth(struct packet_handler *c,
= STATIC_EXCEPTION(EXC_USERAUTH,
"Unknown auth method or service.");
EXCEPTION_RAISE(closure->e, &userauth_failed);
EXCEPTION_RAISE(self->auth_e, &userauth_failed);
return;
}
/* FIXME: Do the user_db lookup here? */
AUTHENTICATE(auth, connection, user, requested_service, &buffer,
make_delay_continuation(service, closure->c),
closure->e);
make_userauth_continuation(connection,
make_apply(service, self->c, self->service_e)),
self->auth_e);
}
else
PROTOCOL_ERROR(connection->e, "Invalid USERAUTH message.");
......@@ -144,11 +213,12 @@ do_handle_userauth(struct packet_handler *c,
lsh_string_free(packet);
}
struct packet_handler *
static struct packet_handler *
make_userauth_handler(struct alist *methods,
struct alist *services,
struct command_continuation *c,
struct exception_handler *e)
struct exception_handler *service_e,
struct exception_handler *auth_e)
{
NEW(userauth_handler, auth);
......@@ -156,35 +226,16 @@ make_userauth_handler(struct alist *methods,
auth->methods = methods;
auth->services = services;
auth->c = c;
auth->e = e;
auth->service_e = service_e;
auth->auth_e = auth_e;
return &auth->super;
}
/* FIXME: This code doesn't handle authentication methods where the
* result (continuation or exception) is not invoked immediately.
* There are two problems:
*
* 1. Requests are not necessarily replied to in order. That is bad,
* but can probably be fixed fairly easily the same way that it is
* done for GLOBAL_REQUEST messages.
*
* 2. Packets that are received after a sucessful USERAUTH_REQUEST
* message, but before it is processed and replied to, must somehow be
* queued until we know that the user is authenticated for some
* service to receive them.
*
* I think the right thing to do is to serialize userauth requests
* completely: if a request can't be replied to immediately, put the
* entire connection on hold until the reply is ready.
*
* This code now uses serialization, using connection_lock() and
* connection_unlock(). However, the implementation of serialization
* is rather stupid. And will crash if a userauth method returns to
* the main loop while the connection is still locked. */
#if 0
/* GABA:
/* ;; GABA:
(class
(name userauth_continuation)
(super command_frame)
......@@ -230,6 +281,7 @@ make_userauth_continuation(struct ssh_connection *connection,
self->connection = connection;
return &self->super.super;
}
#endif
/* GABA:
......@@ -312,17 +364,25 @@ make_exc_userauth_handler(struct ssh_connection *connection,
}
static void do_userauth(struct command *s,
struct lsh_object *x,
struct command_continuation *c,
struct exception_handler *e)
static void
do_userauth(struct command *s,
struct lsh_object *x,
struct command_continuation *c,
struct exception_handler *e)
{
CAST(userauth_service, self, s);
CAST(ssh_connection, connection, x);
if (connection->user)
{
werror("do_userauth: Dropping previous authentication for user '%pS'.\n",
connection->user->name);
connection->user = NULL;
}
connection->dispatch[SSH_MSG_USERAUTH_REQUEST] =
make_userauth_handler(self->methods, self->services,
make_userauth_continuation(connection, c, e),
c, e,
make_exc_userauth_handler(connection,
self->advertised_methods,
AUTH_ATTEMPTS, e,
......
......@@ -90,12 +90,14 @@ format_userauth_failure(struct int_list *methods,
struct lsh_string *
format_userauth_success(void);
struct packet_handler *
#if 0
static struct packet_handler *
make_userauth_handler(struct alist *methods,
struct alist *services,
struct command_continuation *c,
struct exception_handler *e);
struct exception_handler *service_e,
struct exception_handler *auth_e);
#endif
/* authentication methods */
......
Supports Markdown
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