2 * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "krb5_locl.h"
37 * The format seems to be:
41 * KRB5_SENDAUTH_V1.0 (including zero)
43 * protocol string (with terminating zero)
46 * 1 byte - (0 = OK, else some kind of error)
53 * 4 bytes - length (0 = OK, else length of error)
64 * Perform the client side of the sendauth protocol.
66 * @param context Kerberos 5 context.
67 * @param auth_context Authentication context of the peer.
68 * @param p_fd Socket associated to the connection.
69 * @param appl_version Server-specific string.
70 * @param client Client principal. If NULL, use the credentials in \a ccache.
71 * @param server Server principal.
72 * @param ap_req_options Options for the AP_REQ message. See the AP_OPTS_* defines in krb5.h.
73 * @param in_data FIXME
74 * @param in_creds FIXME
75 * @param ccache Credentials cache. If NULL, use the default credentials cache.
76 * @param ret_error If not NULL, will be set to the error reported by server, if any.
77 * Must be deallocated with krb5_free_error_contents().
78 * @param rep_result If not NULL, will be set to the EncApRepPart of the AP_REP message.
79 * Must be deallocated with krb5_free_ap_rep_enc_part().
80 * @param out_creds FIXME If not NULL, will be set to FIXME. Must be deallocated with
83 * @return 0 to indicate success. Otherwise a Kerberos error code is
84 * returned, see krb5_get_error_message().
86 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
87 krb5_sendauth(krb5_context context
,
88 krb5_auth_context
*auth_context
,
90 const char *appl_version
,
91 krb5_principal client
,
92 krb5_principal server
,
93 krb5_flags ap_req_options
,
97 krb5_error
**ret_error
,
98 krb5_ap_rep_enc_part
**rep_result
,
99 krb5_creds
**out_creds
)
102 uint32_t len
, net_len
;
103 const char *version
= KRB5_SENDAUTH_VERSION
;
105 krb5_data ap_req
, error_data
;
106 krb5_creds this_cred
;
107 krb5_principal this_client
= NULL
;
110 krb5_boolean my_ccache
= FALSE
;
112 len
= strlen(version
) + 1;
113 net_len
= htonl(len
);
114 if (krb5_net_write (context
, p_fd
, &net_len
, 4) != 4
115 || krb5_net_write (context
, p_fd
, version
, len
) != len
) {
117 krb5_set_error_message (context
, ret
, "write: %s", strerror(ret
));
121 len
= strlen(appl_version
) + 1;
122 net_len
= htonl(len
);
123 if (krb5_net_write (context
, p_fd
, &net_len
, 4) != 4
124 || krb5_net_write (context
, p_fd
, appl_version
, len
) != len
) {
126 krb5_set_error_message (context
, ret
, "write: %s", strerror(ret
));
130 sret
= krb5_net_read (context
, p_fd
, &repl
, sizeof(repl
));
133 krb5_set_error_message (context
, ret
, "read: %s", strerror(ret
));
135 } else if (sret
!= sizeof(repl
)) {
136 krb5_clear_error_message (context
);
137 return KRB5_SENDAUTH_BADRESPONSE
;
141 krb5_clear_error_message (context
);
142 return KRB5_SENDAUTH_REJECTED
;
145 if (in_creds
== NULL
) {
146 if (ccache
== NULL
) {
147 ret
= krb5_cc_default (context
, &ccache
);
153 if (client
== NULL
) {
154 ret
= krb5_cc_get_principal (context
, ccache
, &this_client
);
157 krb5_cc_close(context
, ccache
);
160 client
= this_client
;
162 memset(&this_cred
, 0, sizeof(this_cred
));
163 this_cred
.client
= client
;
164 this_cred
.server
= server
;
165 this_cred
.times
.endtime
= 0;
166 this_cred
.ticket
.length
= 0;
167 in_creds
= &this_cred
;
169 if (in_creds
->ticket
.length
== 0) {
170 ret
= krb5_get_credentials (context
, 0, ccache
, in_creds
, &creds
);
173 krb5_cc_close(context
, ccache
);
180 krb5_cc_close(context
, ccache
);
181 ret
= krb5_mk_req_extended (context
,
191 krb5_free_creds(context
, creds
);
193 krb5_free_principal(context
, this_client
);
198 ret
= krb5_write_message (context
,
204 krb5_data_free (&ap_req
);
206 ret
= krb5_read_message (context
, p_fd
, &error_data
);
210 if (error_data
.length
!= 0) {
213 ret
= krb5_rd_error (context
, &error_data
, &error
);
214 krb5_data_free (&error_data
);
216 ret
= krb5_error_from_rd_error(context
, &error
, NULL
);
217 if (ret_error
!= NULL
) {
218 *ret_error
= malloc (sizeof(krb5_error
));
219 if (*ret_error
== NULL
) {
220 krb5_free_error_contents (context
, &error
);
225 krb5_free_error_contents (context
, &error
);
229 krb5_clear_error_message(context
);
233 krb5_data_free (&error_data
);
235 if (ap_req_options
& AP_OPTS_MUTUAL_REQUIRED
) {
237 krb5_ap_rep_enc_part
*ignore
= NULL
;
239 krb5_data_zero (&ap_rep
);
240 ret
= krb5_read_message (context
,
246 ret
= krb5_rd_rep (context
, *auth_context
, &ap_rep
,
247 rep_result
? rep_result
: &ignore
);
248 krb5_data_free (&ap_rep
);
251 if (rep_result
== NULL
)
252 krb5_free_ap_rep_enc_part (context
, ignore
);