Main Page | Namespace List | Class List | Directories | File List | Class Members | File Members

auth-krb5.c

Go to the documentation of this file.
00001 /*
00002  *    Kerberos v5 authentication and ticket-passing routines.
00003  *
00004  * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $
00005  */
00006 /*
00007  * Copyright (c) 2002 Daniel Kouril.  All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  * 1. Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer.
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the distribution.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00019  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00020  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00021  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00023  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00024  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00025  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00027  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include "includes.h"
00031 RCSID("$OpenBSD: auth-krb5.c,v 1.16 2005/11/21 09:42:10 dtucker Exp $");
00032 
00033 #include "ssh.h"
00034 #include "ssh1.h"
00035 #include "packet.h"
00036 #include "xmalloc.h"
00037 #include "log.h"
00038 #include "servconf.h"
00039 #include "uidswap.h"
00040 #include "auth.h"
00041 
00042 #ifdef KRB5
00043 #include <krb5.h>
00044 
00045 extern ServerOptions     options;
00046 
00047 static int
00048 krb5_init(void *context)
00049 {
00050         Authctxt *authctxt = (Authctxt *)context;
00051         krb5_error_code problem;
00052 
00053         if (authctxt->krb5_ctx == NULL) {
00054                 problem = krb5_init_context(&authctxt->krb5_ctx);
00055                 if (problem)
00056                         return (problem);
00057         }
00058         return (0);
00059 }
00060 
00061 int
00062 auth_krb5_password(Authctxt *authctxt, const char *password)
00063 {
00064 #ifndef HEIMDAL
00065         krb5_creds creds;
00066         krb5_principal server;
00067 #endif
00068         krb5_error_code problem;
00069         krb5_ccache ccache = NULL;
00070         int len;
00071 
00072         temporarily_use_uid(authctxt->pw);
00073 
00074         problem = krb5_init(authctxt);
00075         if (problem)
00076                 goto out;
00077 
00078         problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name,
00079                     &authctxt->krb5_user);
00080         if (problem)
00081                 goto out;
00082 
00083 #ifdef HEIMDAL
00084         problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
00085         if (problem)
00086                 goto out;
00087 
00088         problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
00089                 authctxt->krb5_user);
00090         if (problem)
00091                 goto out;
00092 
00093         restore_uid();
00094 
00095         problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
00096             ccache, password, 1, NULL);
00097 
00098         temporarily_use_uid(authctxt->pw);
00099 
00100         if (problem)
00101                 goto out;
00102 
00103         problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
00104             &authctxt->krb5_fwd_ccache);
00105         if (problem)
00106                 goto out;
00107 
00108         problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache,
00109             authctxt->krb5_fwd_ccache);
00110         krb5_cc_destroy(authctxt->krb5_ctx, ccache);
00111         ccache = NULL;
00112         if (problem)
00113                 goto out;
00114 
00115 #else
00116         problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
00117             authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL);
00118         if (problem)
00119                 goto out;
00120 
00121         problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
00122             KRB5_NT_SRV_HST, &server);
00123         if (problem)
00124                 goto out;
00125 
00126         restore_uid();
00127         problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
00128             NULL, NULL, NULL);
00129         krb5_free_principal(authctxt->krb5_ctx, server);
00130         temporarily_use_uid(authctxt->pw);
00131         if (problem)
00132                 goto out;
00133 
00134         if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
00135                           authctxt->pw->pw_name)) {
00136                 problem = -1;
00137                 goto out;
00138         }
00139 
00140         problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache);
00141         if (problem)
00142                 goto out;
00143 
00144         problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
00145                                      authctxt->krb5_user);
00146         if (problem)
00147                 goto out;
00148 
00149         problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
00150                                  &creds);
00151         if (problem)
00152                 goto out;
00153 #endif
00154 
00155         authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
00156 
00157         len = strlen(authctxt->krb5_ticket_file) + 6;
00158         authctxt->krb5_ccname = xmalloc(len);
00159         snprintf(authctxt->krb5_ccname, len, "FILE:%s",
00160             authctxt->krb5_ticket_file);
00161 
00162 #ifdef USE_PAM
00163         if (options.use_pam)
00164                 do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname);
00165 #endif
00166 
00167  out:
00168         restore_uid();
00169 
00170         if (problem) {
00171                 if (ccache)
00172                         krb5_cc_destroy(authctxt->krb5_ctx, ccache);
00173 
00174                 if (authctxt->krb5_ctx != NULL && problem!=-1)
00175                         debug("Kerberos password authentication failed: %s",
00176                             krb5_get_err_text(authctxt->krb5_ctx, problem));
00177                 else
00178                         debug("Kerberos password authentication failed: %d",
00179                             problem);
00180 
00181                 krb5_cleanup_proc(authctxt);
00182 
00183                 if (options.kerberos_or_local_passwd)
00184                         return (-1);
00185                 else
00186                         return (0);
00187         }
00188         return (authctxt->valid ? 1 : 0);
00189 }
00190 
00191 void
00192 krb5_cleanup_proc(Authctxt *authctxt)
00193 {
00194         debug("krb5_cleanup_proc called");
00195         if (authctxt->krb5_fwd_ccache) {
00196                 krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
00197                 authctxt->krb5_fwd_ccache = NULL;
00198         }
00199         if (authctxt->krb5_user) {
00200                 krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
00201                 authctxt->krb5_user = NULL;
00202         }
00203         if (authctxt->krb5_ctx) {
00204                 krb5_free_context(authctxt->krb5_ctx);
00205                 authctxt->krb5_ctx = NULL;
00206         }
00207 }
00208 
00209 #ifndef HEIMDAL
00210 krb5_error_code
00211 ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
00212         int tmpfd, ret;
00213         char ccname[40];
00214         mode_t old_umask;
00215 
00216         ret = snprintf(ccname, sizeof(ccname),
00217             "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
00218         if (ret < 0 || (size_t)ret >= sizeof(ccname))
00219                 return ENOMEM;
00220 
00221         old_umask = umask(0177);
00222         tmpfd = mkstemp(ccname + strlen("FILE:"));
00223         umask(old_umask);
00224         if (tmpfd == -1) {
00225                 logit("mkstemp(): %.100s", strerror(errno));
00226                 return errno;
00227         }
00228 
00229         if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
00230                 logit("fchmod(): %.100s", strerror(errno));
00231                 close(tmpfd);
00232                 return errno;
00233         }
00234         close(tmpfd);
00235 
00236         return (krb5_cc_resolve(ctx, ccname, ccache));
00237 }
00238 #endif /* !HEIMDAL */
00239 #endif /* KRB5 */

© sourcejam.com 2005-2008