155682Smarkm/*
272445Sassar * Copyright (c) 1998 - 2001 Kungliga Tekniska H�gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
555682Smarkm *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
955682Smarkm *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "ftpd_locl.h"
3555682Smarkm#include <gssapi.h>
3655682Smarkm#include <krb5.h>
3755682Smarkm
38178825SdfrRCSID("$Id: gss_userok.c 21222 2007-06-20 10:11:14Z lha $");
3955682Smarkm
4055682Smarkm/* XXX a bit too much of krb5 dependency here...
4155682Smarkm   What is the correct way to do this?
4255682Smarkm   */
4355682Smarkm
44178825Sdfrstruct gss_krb5_data {
45178825Sdfr    krb5_context context;
46178825Sdfr};
4755682Smarkm
4855682Smarkm/* XXX sync with gssapi.c */
4955682Smarkmstruct gss_data {
5055682Smarkm    gss_ctx_id_t context_hdl;
5155682Smarkm    char *client_name;
5272445Sassar    gss_cred_id_t delegated_cred_handle;
53178825Sdfr    void *mech_data;
5455682Smarkm};
5555682Smarkm
5655682Smarkmint gss_userok(void*, char*); /* to keep gcc happy */
57178825Sdfrint gss_session(void*, char*); /* to keep gcc happy */
5855682Smarkm
5955682Smarkmint
6055682Smarkmgss_userok(void *app_data, char *username)
6155682Smarkm{
6255682Smarkm    struct gss_data *data = app_data;
63178825Sdfr    krb5_error_code ret;
64178825Sdfr    krb5_principal client;
65178825Sdfr    struct gss_krb5_data *kdata;
66178825Sdfr
67178825Sdfr    kdata = calloc(1, sizeof(struct gss_krb5_data));
68178825Sdfr    if (kdata == NULL)
69178825Sdfr	return 1;
70178825Sdfr    data->mech_data = kdata;
71178825Sdfr
72178825Sdfr    ret = krb5_init_context(&(kdata->context));
73178825Sdfr    if (ret) {
74178825Sdfr	free(kdata);
75178825Sdfr	return 1;
76178825Sdfr    }
77178825Sdfr
78178825Sdfr    ret = krb5_parse_name(kdata->context, data->client_name, &client);
79178825Sdfr    if(ret) {
80178825Sdfr	krb5_free_context(kdata->context);
81178825Sdfr	free(kdata);
82178825Sdfr	return 1;
83178825Sdfr    }
84178825Sdfr    ret = krb5_kuserok(kdata->context, client, username);
85178825Sdfr    if (!ret) {
86178825Sdfr	krb5_free_principal(kdata->context, client);
87178825Sdfr	krb5_free_context(kdata->context);
88178825Sdfr	free(kdata);
89178825Sdfr	return 1;
90178825Sdfr    }
9172445Sassar
92178825Sdfr    ret = 0;
93178825Sdfr    krb5_free_principal(kdata->context, client);
94178825Sdfr    return ret;
95178825Sdfr}
96178825Sdfr
97178825Sdfrint
98178825Sdfrgss_session(void *app_data, char *username)
99178825Sdfr{
100178825Sdfr    struct gss_data *data = app_data;
101178825Sdfr    krb5_error_code ret;
102178825Sdfr    OM_uint32 minor_status;
103178825Sdfr    struct gss_krb5_data *kdata;
104178825Sdfr
105178825Sdfr    ret = 0;
106178825Sdfr
107178825Sdfr    kdata = (struct gss_krb5_data *)(data->mech_data);
10872445Sassar
109178825Sdfr    /* more of krb-depend stuff :-( */
110178825Sdfr    /* gss_add_cred() ? */
111178825Sdfr    if (data->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
112178825Sdfr	krb5_ccache ccache = NULL;
113178825Sdfr	const char* ticketfile;
114178825Sdfr	struct passwd *kpw;
115178825Sdfr
116178825Sdfr	ret = krb5_cc_gen_new(kdata->context, &krb5_fcc_ops, &ccache);
117178825Sdfr	if (ret)
118178825Sdfr	    goto fail;
119178825Sdfr
120178825Sdfr	ticketfile = krb5_cc_get_name(kdata->context, ccache);
12172445Sassar
122178825Sdfr	ret = gss_krb5_copy_ccache(&minor_status,
123178825Sdfr				   data->delegated_cred_handle,
124178825Sdfr				   ccache);
125178825Sdfr	if (ret) {
126178825Sdfr	    ret = 0;
127178825Sdfr	    goto fail;
128178825Sdfr	}
12972445Sassar
130178825Sdfr	do_destroy_tickets = 1;
131178825Sdfr
132178825Sdfr	kpw = getpwnam(username);
13372445Sassar
134178825Sdfr	if (kpw == NULL) {
135178825Sdfr	    unlink(ticketfile);
136178825Sdfr	    ret = 1;
137178825Sdfr	    goto fail;
138178825Sdfr	}
13972445Sassar
140178825Sdfr	chown (ticketfile, kpw->pw_uid, kpw->pw_gid);
14172445Sassar
142178825Sdfr	if (asprintf(&k5ccname, "FILE:%s", ticketfile) != -1) {
143178825Sdfr	    esetenv ("KRB5CCNAME", k5ccname, 1);
144178825Sdfr	}
145178825Sdfr	afslog(NULL, 1);
146178825Sdfr    fail:
147178825Sdfr	if (ccache)
148178825Sdfr	    krb5_cc_close(kdata->context, ccache);
149178825Sdfr    }
15072445Sassar
151178825Sdfr    gss_release_cred(&minor_status, &data->delegated_cred_handle);
152178825Sdfr    krb5_free_context(kdata->context);
153178825Sdfr    free(kdata);
154178825Sdfr    return ret;
15555682Smarkm}
156