[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: wish list for rsh
>>>>> "Leif" == Leif Johansson <leifj@it.su.se> writes:
>> Then again, I rather like the idea behind SASL, so may try
>> implementing that, even if it does mean breaking the ssh
>> standard ;-) I don't think Kerberos 5 has been standardized for
>> ssh anyway.
Leif> I have had the same thoughts myself. Please do!
Anyone willing to look at my patch?
This applies to openssh 1.2.1pre24, Debian version. Watch the
non-standard directory name!
The server side is implemented (as far as I can tell), but more work
needs to be done on client side authentication, mainly in auth-sasl.c,
especially with regard to handling errors, handling callbacks and
interactive responses, obtaining required information for all plugins
(eg serverFQDN). In addition, there might be protocol mismatches
between the server and client, and some things could simply be done
"better".
I think I might need a seperate sasldebug and saslfail for both server
and client, this is why I haven't handled client errors properly yet.
Also, I hope I haven't / won't break any of the design principles ssh
is currently based around. Need to be careful with the multiple data
transfers required for SASL (I think this is OK) and prompting user
for extra details, eg password.
On the plus side, I think I have modified the code so that both the
client and server support a "sasl" authentication type - this required
changing lots of code in lots of different places, but I don't think I
missed anything.
Of course, I haven't put the code anywhere near gcc yet, and dread the
moment.
This is the first time I have tried anything this extensive, so it
probably contains more bugs then Windows ;-).
Improvements welcome!
Final working version even better ;-)
diff -rcN openssh-1.2.1pre24/acconfig.h openssh-1.2.1pre24.new/acconfig.h
*** openssh-1.2.1pre24/acconfig.h Fri Dec 31 09:55:34 1999
--- openssh-1.2.1pre24.new/acconfig.h Thu Jan 27 16:09:30 2000
***************
*** 79,84 ****
--- 79,87 ----
/* Define if you want Kerberos 4 support */
#undef KRB4
+ /* Define if you want SASL support */
+ #undef SASL
+
/* Define if you want AFS support */
#undef AFS
diff -rcN openssh-1.2.1pre24/auth-sasl.c openssh-1.2.1pre24.new/auth-sasl.c
*** openssh-1.2.1pre24/auth-sasl.c Thu Jan 1 10:00:00 1970
--- openssh-1.2.1pre24.new/auth-sasl.c Thu Jan 27 16:22:50 2000
***************
*** 0 ****
--- 1,267 ----
+ /*
+ * Dug Song <dugsong@UMICH.EDU>
+ * Kerberos v4 authentication and ticket-passing routines.
+ */
+
+ #include "includes.h"
+ #include "packet.h"
+ #include "xmalloc.h"
+ #include "ssh.h"
+ #include "servconf.h"
+
+ #ifdef SASL
+ #include <sasl.h>
+ #include <saslutil.h>
+
+ int
+ auth_sasl_client()
+ {
+ int result;
+ sasl_conn_t *conn;
+ sasl_interact_t *client_interact=NULL;
+ unsigned serverinlen;
+ const char *serverin;
+ unsigned result_len;
+ char *result_string;
+
+ result=sasl_client_init(callbacks);
+ if (result!=SASL_OK)
+
+ result=sasl_client_new("imap", /* The service we are using */
+ serverFQDN,/* The fully qualified domain
+ name of the server we're
+ connecting to */
+ NULL,
+ 0,
+ &conn); /* allocated on success */
+ if (result!=SASL_OK)
+
+ do {
+ result=sasl_client_start(
+ conn, /* the same context from above */
+ mechlist, /* the list of mechanisms from the server */
+ NULL,
+ &client_interact, /* filled in if an interaction
+ is needed */
+ &result_string, /* filled in on success */
+ &result_len, /* filled in on success */
+ &mechusing);
+
+ if (result==SASL_INTERACT)
+ {
+
+ }
+ } while (result==SASL_INTERACT);
+
+ if (result != SASL_OK)
+
+ packet_start(SSH_AUTH_SASL);
+ packet_put_string("", 0);
+ packet_send();
+ packet_write_wait();
+
+ packet_read_expect(&plen, SSH_SMSG_AUTH_SASL_RESPONSE);
+ serverin = packet_get_string(&serverinlen);
+ while (1)
+ {
+ do
+ {
+ result=sasl_client_step(
+ conn, /* our context */
+ serverin, /* the data from the server */
+ serverinlen, /* it's length */
+ &client_interact, /* this should be unal
+ located and NULL */
+ &out, /* filled in on success */
+ &outlen); /* filled in on success */
+
+ if (result==SASL_INTERACT)
+ {
+ }
+
+ } while (result==SASL_INTERACT);
+ }
+ sasl_dispose(&conn);
+ sasl_done();
+ return 1;
+ }
+
+ static sasl_callback_t server_callbacks[] = {
+ {
+ SASL_CB_LOG, &sasl_my_log, NULL
+ }, /* {
+ SASL_CB_GETPATH, &getpath, NULL
+ }, */ {
+ SASL_CB_LIST_END, NULL, NULL
+ }
+ };
+
+ static int
+ sasl_my_log(void *context __attribute__((unused)),
+ int priority,
+ const char *message)
+ {
+ const char *label;
+
+ assert(message);
+ switch (priority) {
+ case SASL_LOG_ERR:
+ label = "Error";
+ break;
+ case SASL_LOG_WARNING:
+ label = "Warning";
+ break;
+ case SASL_LOG_INFO:
+ label = "Info";
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ log("%s: %s", label, message);
+ }
+
+ static void
+ sasldebug(int why, const char *what, const char *errstr)
+ {
+ if (errstr)
+ packet_send_debug("%s: %s: %s (%s)",
+ progname,
+ what,
+ sasl_errstring(why, NULL, NULL), errstr);
+ else
+ packet_send_debug("%s: %s: %s",
+ progname,
+ what,
+ sasl_errstring(why, NULL, NULL));
+ }
+
+ static void
+ saslfail(int why, const char *what, const char *errstr)
+ {
+ sasldebug(why, what, errstr);
+ exit(EXIT_FAILURE);
+ }
+
+ int
+ auth_sasl_server(const char *server_user, char **ppszUser)
+ {
+ int result;
+ const char *errstr = NULL;
+ unsigned clientinlen;
+ const char *clientin = packet_get_string(&clientinlen);
+ unsigned result_len;
+ char *result_string;
+
+ result = sasl_server_init(
+ server_callbacks, /* Callbacks supported */
+ "ssh"); /* Name of the application */
+
+ if (result != SASL_OK)
+ {
+ saslfail(result, "Initializing libsasl", NULL);
+ return(-1);
+ }
+
+ result = sasl_server_new("ssh",
+ NULL, /* my fully qualified domain name;
+ NULL says use gethostname() */
+ NULL, /* The user realm used for password
+ lookups; NULL means default to serverFQDN
+ Note: This does not affect Kerberos */
+ NULL, /* Callbacks supported only for this
+ connection */
+ 0, /* I support encryption layers;
+ otherwise pass 0 */
+ &conn);
+
+ if (result != SASL_OK)
+ {
+ saslfail(result, "Allocating sasl connection state", NULL);
+ return(-1);
+ }
+
+
+ result=sasl_listmech(
+ conn, /* The context for this connection */
+ NULL, /* not supported */
+ "{", /* What to prepend the string with */
+ ", ", /* What to seperate mechanisms with */
+ "}", /* What to append to the string */
+ &result_string, /* The produced string. Allocated
+ by library */
+ &string_length, /* length of the string */
+ &number_of_mechanisms); /* Number of mechanisms in the
+ string */
+
+
+ if (result != SASL_OK)
+ {
+ saslfail(result, "Generating client mechanism list", NULL);
+ return(-1);
+ }
+
+ packet_start(SSH_SMSG_AUTH_SASL_RESPONSE);
+ packet_put_string(result_string, result_length);
+ packet_send();
+ packet_write_wait();
+
+ packet_read_expect(&plen, SSH_AUTH_SASL);
+ clientin = packet_get_string(&clientinlen);
+
+ result=sasl_server_start(
+ conn, /* context */
+ mechanism_client_chose,
+ clientin, /* the optional string the client
+ gave us */
+ clientinlen, /* and it's length */
+ &out, /* allocated by library on success. Might
+ not be NULL terminated */
+ &outlen,
+ &errstr); /* error string filled in on failure */
+ if ((result!=SASL_OK) && (result!=SASL_CONTINUE))
+ {
+ saslfail(result, "Starting SASL negotiation", errstr);
+ return(-1);
+ }
+
+ while (result == SASL_CONTINUE) {
+ {
+ assert(data != NULL);
+ packet_start(SSH_SMSG_AUTH_SASL_RESPONSE);
+ packet_put_string(result_string, result_length);
+ packet_send();
+ packet_write_wait();
+
+ packet_read_expect(&plen, SSH_AUTH_SASL);
+ clientin = packet_get_string(&clientinlen);
+
+ result=sasl_server_step(conn,
+ clientin, /* what the client gave */
+ clientinlen, /* it's length */
+ &result_string,/* allocated by library on success.
+ Might not be NULL terminated */
+ &result_length,
+ &errstr); /* error string sometimes filled in
+ on failure */
+ }
+
+ if ((result!=SASL_OK) && (result!=SASL_CONTINUE))
+ {
+ saslfail(result, "Performing SASL negotiation", errstr);
+ return(-1);
+ }
+
+ result = sasl_getprop(conn, SASL_USERNAME, ppszUser);
+ if (result!=SASL_OK)
+ {
+ saslfail(result, "username", NULL);
+ return(-1);
+ }
+
+ sasl_dispose(&conn);
+ sasl_done();
+ return 1;
+ }
+ #endif /* SASL */
diff -rcN openssh-1.2.1pre24/configure.in openssh-1.2.1pre24.new/configure.in
*** openssh-1.2.1pre24/configure.in Fri Dec 31 09:55:34 1999
--- openssh-1.2.1pre24.new/configure.in Thu Jan 27 16:08:26 2000
***************
*** 410,415 ****
--- 410,427 ----
]
)
+ dnl Check whether user wants Kerberos support
+ AC_ARG_WITH(sasl,
+ [ --with-sasl Enable SASL support],
+ [
+ if test "x$withval" != "$xno" ; then
+ AC_DEFINE(SASL)
+ LIBS="$LIBS -lsasl"
+ CFLAGS="$CFLAGS"
+ fi
+ ]
+ )
+
dnl Check whether user wants AFS support
AC_ARG_WITH(afs,
[ --with-afs Enable AFS support],
diff -rcN openssh-1.2.1pre24/readconf.c openssh-1.2.1pre24.new/readconf.c
*** openssh-1.2.1pre24/readconf.c Thu Jan 27 16:09:53 2000
--- openssh-1.2.1pre24.new/readconf.c Thu Jan 27 16:03:34 2000
***************
*** 94,99 ****
--- 94,102 ----
#ifdef KRB4
oKerberosAuthentication,
#endif /* KRB4 */
+ #ifdef SASL
+ oSaslAuthentication,
+ #endif /* SASL */
#ifdef AFS
oKerberosTgtPassing, oAFSTokenPassing,
#endif
***************
*** 122,127 ****
--- 125,133 ----
#ifdef KRB4
{ "kerberosauthentication", oKerberosAuthentication },
#endif /* KRB4 */
+ #ifdef SASL
+ { "saslauthentication", oSaslAuthentication },
+ #endif /* SASL */
#ifdef AFS
{ "kerberostgtpassing", oKerberosTgtPassing },
{ "afstokenpassing", oAFSTokenPassing },
***************
*** 302,307 ****
--- 308,319 ----
goto parse_flag;
#endif /* KRB4 */
+ #ifdef SASL
+ case oSaslAuthentication:
+ intptr = &options->sasl_authentication;
+ goto parse_flag;
+ #endif /* SASL */
+
#ifdef AFS
case oKerberosTgtPassing:
intptr = &options->kerberos_tgt_passing;
***************
*** 597,602 ****
--- 609,617 ----
#ifdef KRB4
options->kerberos_authentication = -1;
#endif
+ #ifdef SASL
+ options->sasl_authentication = -1;
+ #endif
#ifdef AFS
options->kerberos_tgt_passing = -1;
options->afs_token_passing = -1;
***************
*** 652,657 ****
--- 667,676 ----
#ifdef KRB4
if (options->kerberos_authentication == -1)
options->kerberos_authentication = 1;
+ #endif /* KRB4 */
+ #ifdef SASL
+ if (options->sasl_authentication == -1)
+ options->sasl_authentication = 1;
#endif /* KRB4 */
#ifdef AFS
if (options->kerberos_tgt_passing == -1)
diff -rcN openssh-1.2.1pre24/readconf.h openssh-1.2.1pre24.new/readconf.h
*** openssh-1.2.1pre24/readconf.h Thu Jan 27 16:09:53 2000
--- openssh-1.2.1pre24.new/readconf.h Thu Jan 27 15:30:25 2000
***************
*** 41,46 ****
--- 41,50 ----
int kerberos_authentication; /* Try Kerberos
* authentication. */
#endif
+ #ifdef SASL
+ int sasl_authentication; /* Try SASL
+ * authentication. */
+ #endif
#ifdef AFS
int kerberos_tgt_passing; /* Try Kerberos tgt passing. */
int afs_token_passing; /* Try AFS token passing. */
diff -rcN openssh-1.2.1pre24/servconf.c openssh-1.2.1pre24.new/servconf.c
*** openssh-1.2.1pre24/servconf.c Thu Nov 25 11:54:59 1999
--- openssh-1.2.1pre24.new/servconf.c Thu Jan 27 16:06:45 2000
***************
*** 49,54 ****
--- 49,57 ----
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
#endif
+ #ifdef SASL
+ options->sasl_authentication = -1;
+ #endif
#ifdef AFS
options->kerberos_tgt_passing = -1;
options->afs_token_passing = -1;
***************
*** 122,127 ****
--- 125,134 ----
if (options->kerberos_ticket_cleanup == -1)
options->kerberos_ticket_cleanup = 1;
#endif /* KRB4 */
+ #ifdef SASL
+ if (options->sasl_authentication == -1)
+ options->sasl_authentication = 1;
+ #endif /* SASL */
#ifdef AFS
if (options->kerberos_tgt_passing == -1)
options->kerberos_tgt_passing = 0;
***************
*** 151,156 ****
--- 158,166 ----
#ifdef KRB4
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
#endif
+ #ifdef SASL
+ sSaslAuthentication,
+ #endif
#ifdef AFS
sKerberosTgtPassing, sAFSTokenPassing,
#endif
***************
*** 185,190 ****
--- 195,203 ----
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
{ "kerberosticketcleanup", sKerberosTicketCleanup },
#endif
+ #ifdef SASL
+ { "saslauthentication", sSaslAuthentication },
+ #endif
#ifdef AFS
{ "kerberostgtpassing", sKerberosTgtPassing },
{ "afstokenpassing", sAFSTokenPassing },
***************
*** 387,392 ****
--- 400,411 ----
case sKerberosTicketCleanup:
intptr = &options->kerberos_ticket_cleanup;
+ goto parse_flag;
+ #endif
+
+ #ifdef SASL
+ case sSaslAuthentication:
+ intptr = &options->sasl_authentication;
goto parse_flag;
#endif
diff -rcN openssh-1.2.1pre24/servconf.h openssh-1.2.1pre24.new/servconf.h
*** openssh-1.2.1pre24/servconf.h Thu Nov 25 11:54:59 1999
--- openssh-1.2.1pre24.new/servconf.h Thu Jan 27 15:30:49 2000
***************
*** 61,66 ****
--- 61,69 ----
int kerberos_ticket_cleanup; /* If true, destroy ticket
* file on logout. */
#endif
+ #ifdef SASL
+ int sasl_authentication; /* If true, SASL authentication */
+ #endif
#ifdef AFS
int kerberos_tgt_passing; /* If true, permit Kerberos tgt
* passing. */
diff -rcN openssh-1.2.1pre24/ssh.h openssh-1.2.1pre24.new/ssh.h
*** openssh-1.2.1pre24/ssh.h Thu Jan 27 16:09:53 2000
--- openssh-1.2.1pre24.new/ssh.h Thu Jan 27 14:13:26 2000
***************
*** 212,217 ****
--- 212,218 ----
#define SSH_PASS_KERBEROS_TGT 7
/* 8 to 15 are reserved */
#define SSH_PASS_AFS_TOKEN 21
+ #define SSH_AUTH_SASL 22
/* Protocol flags. These are bit masks. */
#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */
***************
*** 270,275 ****
--- 271,277 ----
#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */
#define SSH_CMSG_HAVE_KERBEROS_TGT 44 /* credentials (s) */
#define SSH_CMSG_HAVE_AFS_TOKEN 65 /* token (s) */
+ #define SSH_SMSG_AUTH_SASL_REPLY 66
/*------------ definitions for login.c -------------*/
diff -rcN openssh-1.2.1pre24/sshconnect.c openssh-1.2.1pre24.new/sshconnect.c
*** openssh-1.2.1pre24/sshconnect.c Tue Dec 21 20:57:20 1999
--- openssh-1.2.1pre24.new/sshconnect.c Thu Jan 27 16:22:26 2000
***************
*** 1553,1558 ****
--- 1553,1568 ----
}
#endif /* AFS */
+ #ifdef SASL
+ if ((supported_authentications & (1 << SSH_AUTH_SASL)) &&
+ options.sasl_authentication) {
+ debug("Trying SASL authentication.");
+ if (auth_sasl_client()) {
+ return;
+ }
+ }
+ #endif /* SASL */
+
#ifdef KRB4
if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
options.kerberos_authentication) {
diff -rcN openssh-1.2.1pre24/sshd.c openssh-1.2.1pre24.new/sshd.c
*** openssh-1.2.1pre24/sshd.c Thu Dec 30 15:08:44 1999
--- openssh-1.2.1pre24.new/sshd.c Thu Jan 27 15:05:57 2000
***************
*** 223,228 ****
--- 223,232 ----
case SSH_CMSG_AUTH_KERBEROS:
return "kerberos";
#endif
+ #ifdef SASL
+ case SSH_CMSG_AUTH_KERBEROS:
+ return "kerberos";
+ #endif
#ifdef SKEY
case SSH_CMSG_AUTH_TIS_RESPONSE:
return "s/key";
***************
*** 865,870 ****
--- 869,878 ----
if (options.kerberos_authentication)
auth_mask |= 1 << SSH_AUTH_KERBEROS;
#endif
+ #ifdef SASL
+ if (options.sasl_authentication)
+ auth_mask |= 1 << SSH_AUTH_SASL;
+ #endif
#ifdef AFS
if (options.kerberos_tgt_passing)
auth_mask |= 1 << SSH_PASS_KERBEROS_TGT;
***************
*** 1249,1254 ****
--- 1257,1278 ----
}
break;
#endif /* KRB4 */
+ #ifdef SASL
+ case SSH_CMSG_AUTH_SASL:
+ if (!options.sasl_authentication) {
+ /* packet_get_all(); */
+ verbose("Sasl authentication disabled.");
+ break;
+ } else {
+ char *pszUser;
+ authenticated = auth_sasl_server(pw->pw_name,&pszUser);
+ if (authenticated) {
+ {
+ snprintf(user, sizeof user, " sasl %s", pszUser);
+ }
+ }
+ break;
+ #endif /* SASL */
case SSH_CMSG_AUTH_RHOSTS:
if (!options.rhosts_authentication) {
--
Brian May <bmay@csse.monash.edu.au>