00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
00239 #endif