diff --git a/appl/ftp/ftp/ftp.c b/appl/ftp/ftp/ftp.c index 40ed9433d..ba68bd200 100644 --- a/appl/ftp/ftp/ftp.c +++ b/appl/ftp/ftp/ftp.c @@ -200,7 +200,9 @@ login (char *host) } strlcpy(username, user, sizeof(username)); n = command("USER %s", user); - if (n == CONTINUE) { + if (n == COMPLETE) + n = command("PASS dummy"); /* DK: Compatibility with gssftp daemon */ + else if(n == CONTINUE) { if (pass == NULL) { char prompt[128]; if(myname && diff --git a/appl/ftp/ftp/ftp_var.h b/appl/ftp/ftp/ftp_var.h index ffac59a50..5b9c6e1be 100644 --- a/appl/ftp/ftp/ftp_var.h +++ b/appl/ftp/ftp/ftp_var.h @@ -101,6 +101,7 @@ extern int cpend; /* flag: if != 0, then pending server rep extern int mflag; /* flag: if != 0, then active multi command */ extern int options; /* used during socket creation */ +extern int use_kerberos; /* use Kerberos authentication */ /* * Format of command table. diff --git a/appl/ftp/ftp/globals.c b/appl/ftp/ftp/globals.c index d51ffeef8..296ab669d 100644 --- a/appl/ftp/ftp/globals.c +++ b/appl/ftp/ftp/globals.c @@ -60,6 +60,7 @@ int cpend; /* flag: if != 0, then pending server reply */ int mflag; /* flag: if != 0, then active multi command */ int options; /* used during socket creation */ +int use_kerberos; /* use Kerberos authentication */ /* * Format of command table. diff --git a/appl/ftp/ftp/gssapi.c b/appl/ftp/ftp/gssapi.c index 4db5299a2..8b3b15825 100644 --- a/appl/ftp/ftp/gssapi.c +++ b/appl/ftp/ftp/gssapi.c @@ -43,6 +43,7 @@ RCSID("$Id$"); struct gss_data { gss_ctx_id_t context_hdl; char *client_name; + gss_cred_id_t delegated_cred_handle; }; static int @@ -50,7 +51,17 @@ gss_init(void *app_data) { struct gss_data *d = app_data; d->context_hdl = GSS_C_NO_CONTEXT; + d->delegated_cred_handle = NULL; +#if defined(FTP_SERVER) return 0; +#else + /* XXX Check the gss mechanism; with gss_indicate_mechs() ? */ +#ifdef KRB5 + return !use_kerberos; +#else + return 0 +#endif /* KRB5 */ +#endif /* FTP_SERVER */ } static int @@ -168,6 +179,15 @@ gss_adat(void *app_data, void *buf, size_t len) input_token.value = buf; input_token.length = len; + + d->delegated_cred_handle = malloc(sizeof(*d->delegated_cred_handle)); + if (d->delegated_cred_handle == NULL) { + reply(500, "Out of memory"); + goto out; + } + + memset ((char*)d->delegated_cred_handle, 0, + sizeof(*d->delegated_cred_handle)); maj_stat = gss_accept_sec_context (&min_stat, &d->context_hdl, @@ -179,7 +199,7 @@ gss_adat(void *app_data, void *buf, size_t len) &output_token, NULL, NULL, - NULL); + &d->delegated_cred_handle); if(output_token.length) { if(base64_encode(output_token.value, output_token.length, &p) < 0) { @@ -304,7 +324,8 @@ gss_auth(void *app_data, char *host) &d->context_hdl, target_name, GSS_C_NO_OID, - GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG, + GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG + | GSS_C_DELEG_FLAG, 0, bindings, &input, diff --git a/appl/ftp/ftp/krb4.c b/appl/ftp/ftp/krb4.c index 009ad04a9..d63a24eb6 100644 --- a/appl/ftp/ftp/krb4.c +++ b/appl/ftp/ftp/krb4.c @@ -201,6 +201,12 @@ struct sec_server_mech krb4_server_mech = { #else /* FTP_SERVER */ +static int +krb4_init(void *app_data) +{ + return !use_kerberos; +} + static int mk_auth(struct krb4_data *d, KTEXT adat, char *service, char *host, int checksum) @@ -322,7 +328,7 @@ krb4_auth(void *app_data, char *host) struct sec_client_mech krb4_client_mech = { "KERBEROS_V4", sizeof(struct krb4_data), - NULL, /* init */ + krb4_init, /* init */ krb4_auth, NULL, /* end */ krb4_check_prot, diff --git a/appl/ftp/ftp/main.c b/appl/ftp/ftp/main.c index 5406aab06..fbeddcb75 100644 --- a/appl/ftp/ftp/main.c +++ b/appl/ftp/ftp/main.c @@ -55,8 +55,9 @@ main(int argc, char **argv) interactive = 1; autologin = 1; passivemode = 0; /* passive mode not active */ + use_kerberos = 1; - while ((ch = getopt(argc, argv, "dginptv")) != -1) { + while ((ch = getopt(argc, argv, "dginptvK")) != -1) { switch (ch) { case 'd': options |= SO_DEBUG; @@ -86,9 +87,14 @@ main(int argc, char **argv) verbose++; break; + case 'K': + /* Disable Kerberos authentication */ + use_kerberos = 0; + break; + default: fprintf(stderr, - "usage: ftp [-dginptv] [host [port]]\n"); + "usage: ftp [-dginptvK] [host [port]]\n"); exit(1); } } diff --git a/appl/ftp/ftpd/ftpd_locl.h b/appl/ftp/ftpd/ftpd_locl.h index 52496f6c9..f6db68e35 100644 --- a/appl/ftp/ftpd/ftpd_locl.h +++ b/appl/ftp/ftpd/ftpd_locl.h @@ -147,6 +147,10 @@ #include #include #endif + +#ifdef KRB5 +#include +#endif /* KRB5 */ #ifdef OTP #include diff --git a/appl/ftp/ftpd/gss_userok.c b/appl/ftp/ftpd/gss_userok.c index f3b9bf8ae..92a3d0d80 100644 --- a/appl/ftp/ftpd/gss_userok.c +++ b/appl/ftp/ftpd/gss_userok.c @@ -47,6 +47,7 @@ extern krb5_context gssapi_krb5_context; struct gss_data { gss_ctx_id_t context_hdl; char *client_name; + gss_cred_id_t delegated_cred_handle; }; int gss_userok(void*, char*); /* to keep gcc happy */ @@ -58,12 +59,58 @@ gss_userok(void *app_data, char *username) if(gssapi_krb5_context) { krb5_principal client; krb5_error_code ret; + ret = krb5_parse_name(gssapi_krb5_context, data->client_name, &client); if(ret) return 1; ret = krb5_kuserok(gssapi_krb5_context, client, username); + if (!ret) { + krb5_free_principal(gssapi_krb5_context, client); + return 1; + } + + ret = 0; + + /* more of krb-depend stuff :-( */ + /* gss_add_cred() ? */ + if (data->delegated_cred_handle && + data->delegated_cred_handle->ccache ) { + + krb5_ccache ccache = NULL; + char* ticketfile; + struct passwd *pw; + + pw = getpwnam(username); + + asprintf (&ticketfile, "%s%u", KRB5_DEFAULT_CCROOT, pw->pw_uid); + + ret = krb5_cc_resolve(gssapi_krb5_context, ticketfile, &ccache); + if (ret) + goto fail; + + ret = krb5_cc_copy_cache(gssapi_krb5_context, + data->delegated_cred_handle->ccache, ccache); + if (ret) + goto fail; + + chown (ticketfile+5, pw->pw_uid, pw->pw_gid); + + if (k_hasafs()) { + krb5_afslog(gssapi_krb5_context, ccache, 0, 0); + } + setenv ("KRB5CCNAME", ticketfile, 1); + +fail: + if (ccache) + krb5_cc_close(gssapi_krb5_context, ccache); + krb5_cc_destroy(gssapi_krb5_context, + data->delegated_cred_handle->ccache); + data->delegated_cred_handle->ccache = NULL; + free(ticketfile); + } + krb5_free_principal(gssapi_krb5_context, client); - return !ret; + return ret; } return 1; }