Check for NULL return from getpwnam_shadow
[login_krb5.git] / login_krb5 / login_krb5.c
blob99c1398c262f545357c092a65f45151ee8fd22be
1 /* $OpenBSD: login_krb5.c,v 1.27 2013/06/21 13:35:26 ajacoutot Exp $ */
3 /*-
4 * Copyright (c) 2001, 2002 Hans Insulander <hin@openbsd.org>.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 #include "common.h"
31 #include <krb5.h>
33 krb5_error_code ret;
34 krb5_context context;
35 krb5_ccache ccache;
36 krb5_principal princ;
38 char *__progname;
40 static void
41 krb5_syslog(krb5_context context, int level, krb5_error_code code, char *fmt, ...)
43 va_list ap;
44 char buf[256];
45 const char *s = krb5_get_error_message(context, code);
47 va_start(ap, fmt);
48 vsnprintf(buf, sizeof(buf), fmt, ap);
49 va_end(ap);
50 syslog(level, "%s: %s", buf, s);
51 krb5_free_error_message(context, s);
54 static void
55 store_tickets(struct passwd *pwd, int ticket_newfiles, int ticket_store,
56 int token_install)
58 char cc_file[PATH_MAX];
59 krb5_ccache ccache_store;
61 if (ticket_newfiles)
62 snprintf(cc_file, sizeof(cc_file), "FILE:/tmp/krb5cc_%d",
63 pwd->pw_uid);
64 else
65 snprintf(cc_file, sizeof(cc_file), "%s",
66 krb5_cc_default_name(context));
68 if (ticket_store) {
69 ret = krb5_cc_resolve(context, cc_file, &ccache_store);
70 if (ret != 0) {
71 krb5_syslog(context, LOG_ERR, ret,
72 "krb5_cc_resolve");
73 exit(1);
76 ret = krb5_cc_copy_cache(context, ccache, ccache_store);
77 if (ret != 0)
78 krb5_syslog(context, LOG_ERR, ret,
79 "krb5_cc_copy_cache");
81 chown(krb5_cc_get_name(context, ccache_store),
82 pwd->pw_uid, pwd->pw_gid);
84 fprintf(back, BI_SETENV " KRB5CCNAME %s:%s\n",
85 krb5_cc_get_type(context, ccache_store),
86 krb5_cc_get_name(context, ccache_store));
90 int
91 krb5_login(char *username, char *invokinguser, char *password, int login,
92 int tickets, char *class)
94 login_cap_t *lc;
95 int return_code = AUTH_FAILED;
96 int noverify = 0;
98 if (username == NULL || password == NULL)
99 return (AUTH_FAILED);
101 if (strcmp(__progname, "-krb5-or-pwd") == 0 &&
102 strcmp(username,"root") == 0 && invokinguser[0] == '\0')
103 return (AUTH_FAILED);
105 lc = login_getclass(class);
106 if (lc != NULL)
107 noverify = login_getcapbool(lc, "krb5-noverify", noverify);
109 ret = krb5_init_context(&context);
110 if (ret != 0) {
111 krb5_syslog(context, LOG_ERR, ret, "krb5_init_context");
112 exit(1);
115 ret = krb5_cc_new_unique(context, krb5_mcc_ops.prefix, NULL, &ccache);
116 if (ret != 0) {
117 krb5_syslog(context, LOG_ERR, ret, "krb5_cc_new_unique");
118 exit(1);
121 if (strcmp(username, "root") == 0 && invokinguser[0] != '\0') {
122 char *tmp;
124 ret = asprintf(&tmp, "%s/root", invokinguser);
125 if (ret == -1) {
126 krb5_syslog(context, LOG_ERR, ret, "asprintf");
127 exit(1);
129 ret = krb5_parse_name(context, tmp, &princ);
130 free(tmp);
131 } else
132 ret = krb5_parse_name(context, username, &princ);
133 if (ret != 0) {
134 krb5_syslog(context, LOG_ERR, ret, "krb5_parse_name");
135 exit(1);
138 ret = krb5_verify_user_lrealm(context, princ, ccache,
139 password, !noverify, NULL);
141 switch (ret) {
142 case 0: {
143 struct passwd *pwd;
145 pwd = getpwnam(username);
146 if (pwd == NULL) {
147 krb5_syslog(context, LOG_ERR, ret,
148 "%s: no such user", username);
149 return (AUTH_FAILED);
151 fprintf(back, BI_AUTH "\n");
152 store_tickets(pwd, login && tickets, login && tickets, login);
153 return_code = AUTH_OK;
154 break;
156 case KRB5KRB_AP_ERR_MODIFIED:
157 krb5_syslog(context, LOG_ERR, ret, "KRB5KRB_AP_ERR_MODIFIED");
158 break;
159 case KRB5KRB_AP_ERR_BAD_INTEGRITY:
160 krb5_syslog(context, LOG_ERR, ret, "KRB5KRB_AP_ERR_BAD_INTEGRITY");
161 break;
162 default:
163 krb5_syslog(context, LOG_ERR, ret, "verify");
164 break;
167 krb5_free_principal(context, princ);
168 krb5_cc_close(context, ccache);
169 krb5_free_context(context);
171 return (return_code);