2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
8 * lib/krb5/krb/recvauth.c
10 * Copyright 1991 by the Massachusetts Institute of Technology.
11 * All Rights Reserved.
13 * Export of this software from the United States of America may
14 * require a specific license from the United States Government.
15 * It is the responsibility of any person or organization contemplating
16 * export to obtain such a license before exporting.
18 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
19 * distribute this software and its documentation for any purpose and
20 * without fee is hereby granted, provided that the above copyright
21 * notice appear in all copies and that both that copyright notice and
22 * this permission notice appear in supporting documentation, and that
23 * the name of M.I.T. not be used in advertising or publicity pertaining
24 * to distribution of the software without specific, written prior
25 * permission. Furthermore if you modify this software you must label
26 * your software as modified software and not distribute it in such a
27 * fashion that it might be confused with the original M.I.T. software.
28 * M.I.T. makes no representations about the suitability of
29 * this software for any purpose. It is provided "as is" without express
30 * or implied warranty.
33 * convenience sendauth/recvauth functions
43 static const char sendauth_version
[] = "KRB5_SENDAUTH_V1.0";
45 static krb5_error_code
46 recvauth_common(krb5_context context
,
47 krb5_auth_context
* auth_context
,
51 krb5_principal server
,
55 krb5_ticket
** ticket
,
58 krb5_auth_context new_auth_context
;
60 krb5_error_code retval
, problem
;
63 krb5_rcache rcache
= 0;
65 krb5_data null_server
;
66 int need_error_free
= 0;
67 int local_rcache
= 0, local_authcon
= 0;
70 * Zero out problem variable. If problem is set at the end of
71 * the intial version negotiation section, it means that we
72 * need to send an error code back to the client application
77 if (!(flags
& KRB5_RECVAUTH_SKIP_VERSION
)) {
79 * First read the sendauth version string and check it.
81 if ((retval
= krb5_read_message(context
, fd
, &inbuf
)))
83 if (strcmp(inbuf
.data
, sendauth_version
)) {
84 problem
= KRB5_SENDAUTH_BADAUTHVERS
;
86 krb5_xfree(inbuf
.data
);
88 if (flags
& KRB5_RECVAUTH_BADAUTHVERS
)
89 problem
= KRB5_SENDAUTH_BADAUTHVERS
;
92 * Do the same thing for the application version string.
94 if ((retval
= krb5_read_message(context
, fd
, &inbuf
)))
96 if (appl_version
&& strcmp(inbuf
.data
, appl_version
)) {
98 problem
= KRB5_SENDAUTH_BADAPPLVERS
;
100 if (version
&& !problem
)
103 krb5_xfree(inbuf
.data
);
105 * OK, now check the problem variable. If it's zero, we're
106 * fine and we can continue. Otherwise, we have to signal an
107 * error to the client side and bail out.
113 case KRB5_SENDAUTH_BADAUTHVERS
:
116 case KRB5_SENDAUTH_BADAPPLVERS
:
121 * Should never happen!
124 #ifdef SENDAUTH_DEBUG
125 fprintf(stderr
, "Programming botch in recvauth! problem = %d",
132 * Now we actually write the response. If the response is non-zero,
133 * exit with a return value of problem
135 if ((krb5_net_write(context
, *((int *)fd
), (char *)&response
, 1)) < 0) {
136 return(problem
); /* We'll return the top-level problem */
141 /* We are clear of errors here */
144 * Now, let's read the AP_REQ message and decode it
146 if ((retval
= krb5_read_message(context
, fd
, &inbuf
)))
149 if (*auth_context
== NULL
) {
150 problem
= krb5_auth_con_init(context
, &new_auth_context
);
151 *auth_context
= new_auth_context
;
154 krb5_auth_con_getrcache(context
, *auth_context
, &rcache
);
155 if ((!problem
) && rcache
== NULL
) {
157 * Setup the replay cache.
160 problem
= krb5_get_server_rcache(context
,
161 krb5_princ_component(context
, server
, 0), &rcache
);
163 null_server
.length
= 7;
164 null_server
.data
= "default";
165 problem
= krb5_get_server_rcache(context
, &null_server
, &rcache
);
168 problem
= krb5_auth_con_setrcache(context
, *auth_context
, rcache
);
172 problem
= krb5_rd_req(context
, auth_context
, &inbuf
, server
,
173 keytab
, &ap_option
, ticket
);
174 krb5_xfree(inbuf
.data
);
178 * If there was a problem, send back a krb5_error message,
179 * preceeded by the length of the krb5_error message. If
180 * everything's ok, send back 0 for the length.
186 memset((char *)&error
, 0, sizeof(error
));
187 krb5_us_timeofday(context
, &error
.stime
, &error
.susec
);
189 error
.server
= server
;
191 /* If this fails - ie. ENOMEM we are hosed
192 we cannot even send the error if we wanted to... */
193 (void) krb5_parse_name(context
, "????", &error
.server
);
197 error
.error
= problem
- ERROR_TABLE_BASE_krb5
;
198 if (error
.error
> 127)
199 error
.error
= KRB_ERR_GENERIC
;
200 message
= error_message(problem
);
201 error
.text
.length
= strlen(message
) + 1;
202 if (!(error
.text
.data
= malloc(error
.text
.length
))) {
206 strcpy(error
.text
.data
, message
);
207 /* Solaris Kerberos */
208 if ((retval
= krb5_mk_error(context
, &error
, &outbuf
)) != 0) {
209 free(error
.text
.data
);
212 free(error
.text
.data
);
214 krb5_free_principal(context
, error
.server
);
221 retval
= krb5_write_message(context
, fd
, &outbuf
);
223 krb5_xfree(outbuf
.data
);
224 /* We sent back an error, we need cleanup then return */
231 /* Here lies the mutual authentication stuff... */
232 if ((ap_option
& AP_OPTS_MUTUAL_REQUIRED
)) {
233 if ((retval
= krb5_mk_rep(context
, *auth_context
, &outbuf
))) {
236 retval
= krb5_write_message(context
, fd
, &outbuf
);
237 krb5_xfree(outbuf
.data
);
243 krb5_auth_con_free(context
, *auth_context
);
244 /* Solaris Kerberos */
245 *auth_context
= NULL
;
246 } else if (local_rcache
&& rcache
!= NULL
) {
247 /* Solaris Kerberos */
248 (void) krb5_rc_close(context
, rcache
);
249 krb5_auth_con_setrcache(context
, *auth_context
, NULL
);
255 krb5_error_code KRB5_CALLCONV
256 krb5_recvauth(krb5_context context
, krb5_auth_context
*auth_context
, krb5_pointer fd
, char *appl_version
, krb5_principal server
, krb5_int32 flags
, krb5_keytab keytab
, krb5_ticket
**ticket
)
258 return recvauth_common (context
, auth_context
, fd
, appl_version
,
259 server
, flags
, keytab
, ticket
, 0);
262 krb5_error_code KRB5_CALLCONV
263 krb5_recvauth_version(krb5_context context
,
264 krb5_auth_context
*auth_context
,
267 krb5_principal server
,
271 krb5_ticket
**ticket
,
274 return recvauth_common (context
, auth_context
, fd
, 0,
275 server
, flags
, keytab
, ticket
, version
);