2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 * Copyright (c) 2016 by Delphix. All rights reserved.
9 * lib/krb5/krb/sendauth.c
11 * Copyright 1991 by the Massachusetts Institute of Technology.
12 * All Rights Reserved.
14 * Export of this software from the United States of America may
15 * require a specific license from the United States Government.
16 * It is the responsibility of any person or organization contemplating
17 * export to obtain such a license before exporting.
19 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
20 * distribute this software and its documentation for any purpose and
21 * without fee is hereby granted, provided that the above copyright
22 * notice appear in all copies and that both that copyright notice and
23 * this permission notice appear in supporting documentation, and that
24 * the name of M.I.T. not be used in advertising or publicity pertaining
25 * to distribution of the software without specific, written prior
26 * permission. Furthermore if you modify this software you must label
27 * your software as modified software and not distribute it in such a
28 * fashion that it might be confused with the original M.I.T. software.
29 * M.I.T. makes no representations about the suitability of
30 * this software for any purpose. It is provided "as is" without express
31 * or implied warranty.
34 * convenience sendauth/recvauth functions
45 static const char sendauth_version
[] = "KRB5_SENDAUTH_V1.0";
47 krb5_error_code KRB5_CALLCONV
48 krb5_sendauth(krb5_context context
, krb5_auth_context
*auth_context
, krb5_pointer fd
, char *appl_version
, krb5_principal client
, krb5_principal server
, krb5_flags ap_req_options
, krb5_data
*in_data
, krb5_creds
*in_creds
, krb5_ccache ccache
, krb5_error
**error
, krb5_ap_rep_enc_part
**rep_result
, krb5_creds
**out_creds
)
52 krb5_creds
* credsp
= NULL
;
53 krb5_creds
* credspout
= NULL
;
54 krb5_error_code retval
= 0;
55 krb5_data inbuf
, outbuf
;
57 krb5_ccache use_ccache
= 0;
63 * First, send over the length of the sendauth version string;
64 * then, we send over the sendauth version. Next, we send
65 * over the length of the application version strings followed
66 * by the string itself.
68 outbuf
.length
= strlen(sendauth_version
) + 1;
69 outbuf
.data
= (char *) sendauth_version
;
70 if ((retval
= krb5_write_message(context
, fd
, &outbuf
)))
72 outbuf
.length
= strlen(appl_version
) + 1;
73 outbuf
.data
= appl_version
;
74 if ((retval
= krb5_write_message(context
, fd
, &outbuf
)))
77 * Now, read back a byte: 0 means no error, 1 means bad sendauth
78 * version, 2 means bad application version
80 len
= krb5_net_read(context
, *((int *) fd
), (char *)&result
, 1);
82 return((len
< 0) ? errno
: ECONNABORTED
);
84 return(KRB5_SENDAUTH_BADAUTHVERS
);
86 return(KRB5_SENDAUTH_BADAPPLVERS
);
88 return(KRB5_SENDAUTH_BADRESPONSE
);
90 * We're finished with the initial negotiations; let's get and
91 * send over the authentication header. (The AP_REQ message)
95 * If no credentials were provided, try getting it from the
98 memset((char *)&creds
, 0, sizeof(creds
));
101 * See if we need to access the credentials cache
103 if (!in_creds
|| !in_creds
->ticket
.length
) {
106 /* Solaris Kerberos */
107 else if ((retval
= krb5int_cc_default(context
, &use_ccache
)) != 0)
111 if ((retval
= krb5_copy_principal(context
, server
,
115 retval
= krb5_copy_principal(context
, client
,
118 retval
= krb5_cc_get_principal(context
, use_ccache
,
121 krb5_free_principal(context
, creds
.server
);
124 /* creds.times.endtime = 0; -- memset 0 takes care of this
125 zero means "as long as possible" */
126 /* creds.keyblock.enctype = 0; -- as well as this.
127 zero means no session enctype
131 if (!in_creds
->ticket
.length
) {
132 /* Solaris Kerberos */
133 if ((retval
= krb5_get_credentials(context
, 0,
134 use_ccache
, in_creds
, &credsp
)) != 0)
141 if (ap_req_options
& AP_OPTS_USE_SUBKEY
) {
142 /* Provide some more fodder for random number code.
143 This isn't strong cryptographically; the point here is
144 not to guarantee randomness, but to make it less likely
145 that multiple sessions could pick the same subkey. */
147 GETPEERNAME_ARG3_TYPE len2
;
149 d
.length
= sizeof (rnd_data
);
151 len2
= sizeof (rnd_data
);
152 if (getpeername (*(int*)fd
, (GETPEERNAME_ARG2_TYPE
*) rnd_data
,
155 /* Solaris Kerberos */
156 (void) krb5_c_random_seed (context
, &d
);
158 len2
= sizeof (rnd_data
);
159 if (getsockname (*(int*)fd
, (GETSOCKNAME_ARG2_TYPE
*) rnd_data
,
162 /* Solaris Kerberos */
163 (void) krb5_c_random_seed (context
, &d
);
167 /* Solaris Kerberos */
168 if ((retval
= krb5_mk_req_extended(context
, auth_context
,
169 ap_req_options
, in_data
, credsp
,
174 * First write the length of the AP_REQ message, then write
175 * the message itself.
177 retval
= krb5_write_message(context
, fd
, &outbuf
);
183 * Now, read back a message. If it was a null message (the
184 * length was zero) then there was no error. If not, we the
185 * authentication was rejected, and we need to return the
188 /* Solaris Kerberos */
189 if ((retval
= krb5_read_message(context
, fd
, &inbuf
)) != 0)
194 /* Solaris Kerberos */
195 if ((retval
= krb5_rd_error(context
, &inbuf
, error
)) != 0) {
196 krb5_xfree(inbuf
.data
);
200 retval
= KRB5_SENDAUTH_REJECTED
;
201 krb5_xfree(inbuf
.data
);
206 * If we asked for mutual authentication, we should now get a
207 * length field, followed by a AP_REP message
209 if ((ap_req_options
& AP_OPTS_MUTUAL_REQUIRED
)) {
210 krb5_ap_rep_enc_part
*repl
= 0;
211 /* Solaris Kerberos */
212 if ((retval
= krb5_read_message(context
, fd
, &inbuf
)) != 0)
215 /* Solaris Kerberos */
216 if ((retval
= krb5_rd_rep(context
, *auth_context
, &inbuf
,
219 krb5_free_ap_rep_enc_part(context
, repl
);
220 krb5_xfree(inbuf
.data
);
224 krb5_xfree(inbuf
.data
);
226 * If the user wants to look at the AP_REP message,
232 krb5_free_ap_rep_enc_part(context
, repl
);
234 retval
= 0; /* Normal return */
241 krb5_free_cred_contents(context
, &creds
);
242 if (credspout
!= NULL
)
243 krb5_free_creds(context
, credspout
);
244 /* Solaris Kerberos */
245 if (!ccache
&& use_ccache
)
246 (void) krb5_cc_close(context
, use_ccache
);