add delegation. From Daniel Kouril <kouril@ics.muni.cz> and Miroslav Ruda <ruda@ics.muni.cz>
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@8434 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
		@@ -200,7 +200,9 @@ login (char *host)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    strlcpy(username, user, sizeof(username));
 | 
					    strlcpy(username, user, sizeof(username));
 | 
				
			||||||
    n = command("USER %s", user);
 | 
					    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) {
 | 
						if (pass == NULL) {
 | 
				
			||||||
	    char prompt[128];
 | 
						    char prompt[128];
 | 
				
			||||||
	    if(myname && 
 | 
						    if(myname && 
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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	mflag;			/* flag: if != 0, then active multi command */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int	options;		/* used during socket creation */
 | 
					extern int	options;		/* used during socket creation */
 | 
				
			||||||
 | 
					extern int      use_kerberos;           /* use Kerberos authentication */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Format of command table.
 | 
					 * Format of command table.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,6 +60,7 @@ int     cpend;                  /* flag: if != 0, then pending server reply */
 | 
				
			|||||||
int	mflag;			/* flag: if != 0, then active multi command */
 | 
					int	mflag;			/* flag: if != 0, then active multi command */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int	options;		/* used during socket creation */
 | 
					int	options;		/* used during socket creation */
 | 
				
			||||||
 | 
					int     use_kerberos;           /* use Kerberos authentication */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Format of command table.
 | 
					 * Format of command table.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,6 +43,7 @@ RCSID("$Id$");
 | 
				
			|||||||
struct gss_data {
 | 
					struct gss_data {
 | 
				
			||||||
    gss_ctx_id_t context_hdl;
 | 
					    gss_ctx_id_t context_hdl;
 | 
				
			||||||
    char *client_name;
 | 
					    char *client_name;
 | 
				
			||||||
 | 
					    gss_cred_id_t delegated_cred_handle;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
@@ -50,7 +51,17 @@ gss_init(void *app_data)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    struct gss_data *d = app_data;
 | 
					    struct gss_data *d = app_data;
 | 
				
			||||||
    d->context_hdl = GSS_C_NO_CONTEXT;
 | 
					    d->context_hdl = GSS_C_NO_CONTEXT;
 | 
				
			||||||
 | 
					    d->delegated_cred_handle = NULL;
 | 
				
			||||||
 | 
					#if defined(FTP_SERVER)
 | 
				
			||||||
    return 0;
 | 
					    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
 | 
					static int
 | 
				
			||||||
@@ -169,6 +180,15 @@ gss_adat(void *app_data, void *buf, size_t len)
 | 
				
			|||||||
    input_token.value = buf;
 | 
					    input_token.value = buf;
 | 
				
			||||||
    input_token.length = len;
 | 
					    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,
 | 
					    maj_stat = gss_accept_sec_context (&min_stat,
 | 
				
			||||||
				       &d->context_hdl,
 | 
									       &d->context_hdl,
 | 
				
			||||||
				       GSS_C_NO_CREDENTIAL,
 | 
									       GSS_C_NO_CREDENTIAL,
 | 
				
			||||||
@@ -179,7 +199,7 @@ gss_adat(void *app_data, void *buf, size_t len)
 | 
				
			|||||||
				       &output_token,
 | 
									       &output_token,
 | 
				
			||||||
				       NULL,
 | 
									       NULL,
 | 
				
			||||||
				       NULL,
 | 
									       NULL,
 | 
				
			||||||
				       NULL);
 | 
					                                       &d->delegated_cred_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(output_token.length) {
 | 
					    if(output_token.length) {
 | 
				
			||||||
	if(base64_encode(output_token.value, output_token.length, &p) < 0) {
 | 
						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,
 | 
										&d->context_hdl,
 | 
				
			||||||
					target_name,
 | 
										target_name,
 | 
				
			||||||
					GSS_C_NO_OID,
 | 
										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,
 | 
										0,
 | 
				
			||||||
					bindings,
 | 
										bindings,
 | 
				
			||||||
					&input,
 | 
										&input,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -201,6 +201,12 @@ struct sec_server_mech krb4_server_mech = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#else /* FTP_SERVER */
 | 
					#else /* FTP_SERVER */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					krb4_init(void *app_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					   return !use_kerberos;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
mk_auth(struct krb4_data *d, KTEXT adat, 
 | 
					mk_auth(struct krb4_data *d, KTEXT adat, 
 | 
				
			||||||
	char *service, char *host, int checksum)
 | 
						char *service, char *host, int checksum)
 | 
				
			||||||
@@ -322,7 +328,7 @@ krb4_auth(void *app_data, char *host)
 | 
				
			|||||||
struct sec_client_mech krb4_client_mech = {
 | 
					struct sec_client_mech krb4_client_mech = {
 | 
				
			||||||
    "KERBEROS_V4",
 | 
					    "KERBEROS_V4",
 | 
				
			||||||
    sizeof(struct krb4_data),
 | 
					    sizeof(struct krb4_data),
 | 
				
			||||||
    NULL, /* init */
 | 
					    krb4_init, /* init */
 | 
				
			||||||
    krb4_auth,
 | 
					    krb4_auth,
 | 
				
			||||||
    NULL, /* end */
 | 
					    NULL, /* end */
 | 
				
			||||||
    krb4_check_prot,
 | 
					    krb4_check_prot,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,8 +55,9 @@ main(int argc, char **argv)
 | 
				
			|||||||
	interactive = 1;
 | 
						interactive = 1;
 | 
				
			||||||
	autologin = 1;
 | 
						autologin = 1;
 | 
				
			||||||
	passivemode = 0; /* passive mode not active */
 | 
						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) {
 | 
							switch (ch) {
 | 
				
			||||||
		case 'd':
 | 
							case 'd':
 | 
				
			||||||
			options |= SO_DEBUG;
 | 
								options |= SO_DEBUG;
 | 
				
			||||||
@@ -86,9 +87,14 @@ main(int argc, char **argv)
 | 
				
			|||||||
			verbose++;
 | 
								verbose++;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case 'K':
 | 
				
			||||||
 | 
					                        /* Disable Kerberos authentication */
 | 
				
			||||||
 | 
					                        use_kerberos = 0;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
		    fprintf(stderr,
 | 
							    fprintf(stderr,
 | 
				
			||||||
			    "usage: ftp [-dginptv] [host [port]]\n");
 | 
					                            "usage: ftp [-dginptvK] [host [port]]\n");
 | 
				
			||||||
		    exit(1);
 | 
							    exit(1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -148,6 +148,10 @@
 | 
				
			|||||||
#include <kafs.h>
 | 
					#include <kafs.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 | 
					#ifdef KRB5
 | 
				
			||||||
 | 
					#include <krb5.h>
 | 
				
			||||||
 | 
					#endif /* KRB5 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef OTP
 | 
					#ifdef OTP
 | 
				
			||||||
#include <otp.h>
 | 
					#include <otp.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,6 +47,7 @@ extern krb5_context gssapi_krb5_context;
 | 
				
			|||||||
struct gss_data {
 | 
					struct gss_data {
 | 
				
			||||||
    gss_ctx_id_t context_hdl;
 | 
					    gss_ctx_id_t context_hdl;
 | 
				
			||||||
    char *client_name;
 | 
					    char *client_name;
 | 
				
			||||||
 | 
					    gss_cred_id_t delegated_cred_handle;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int gss_userok(void*, char*); /* to keep gcc happy */
 | 
					int gss_userok(void*, char*); /* to keep gcc happy */
 | 
				
			||||||
@@ -58,12 +59,58 @@ gss_userok(void *app_data, char *username)
 | 
				
			|||||||
    if(gssapi_krb5_context) {
 | 
					    if(gssapi_krb5_context) {
 | 
				
			||||||
	krb5_principal client;
 | 
						krb5_principal client;
 | 
				
			||||||
	krb5_error_code ret;
 | 
						krb5_error_code ret;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
	ret = krb5_parse_name(gssapi_krb5_context, data->client_name, &client);
 | 
						ret = krb5_parse_name(gssapi_krb5_context, data->client_name, &client);
 | 
				
			||||||
	if(ret)
 | 
						if(ret)
 | 
				
			||||||
	    return 1;
 | 
						    return 1;
 | 
				
			||||||
	ret = krb5_kuserok(gssapi_krb5_context, client, username);
 | 
						ret = krb5_kuserok(gssapi_krb5_context, client, username);
 | 
				
			||||||
 | 
					        if (!ret) {
 | 
				
			||||||
           krb5_free_principal(gssapi_krb5_context, client);
 | 
					           krb5_free_principal(gssapi_krb5_context, client);
 | 
				
			||||||
	return !ret;
 | 
					           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 1;
 | 
					    return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user