1 /* $NetBSD: recvauth.c,v 1.1.1.1 2011/04/13 18:15:37 elric Exp $ */
2
3 /*
4 * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include "krb5_locl.h"
37
38 /*
39 * See `sendauth.c' for the format.
40 */
41
42 static krb5_boolean
match_exact(const void * data,const char * appl_version)43 match_exact(const void *data, const char *appl_version)
44 {
45 return strcmp(data, appl_version) == 0;
46 }
47
48 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_recvauth(krb5_context context,krb5_auth_context * auth_context,krb5_pointer p_fd,const char * appl_version,krb5_principal server,int32_t flags,krb5_keytab keytab,krb5_ticket ** ticket)49 krb5_recvauth(krb5_context context,
50 krb5_auth_context *auth_context,
51 krb5_pointer p_fd,
52 const char *appl_version,
53 krb5_principal server,
54 int32_t flags,
55 krb5_keytab keytab,
56 krb5_ticket **ticket)
57 {
58 return krb5_recvauth_match_version(context, auth_context, p_fd,
59 match_exact, appl_version,
60 server, flags,
61 keytab, ticket);
62 }
63
64 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_recvauth_match_version(krb5_context context,krb5_auth_context * auth_context,krb5_pointer p_fd,krb5_boolean (* match_appl_version)(const void *,const char *),const void * match_data,krb5_principal server,int32_t flags,krb5_keytab keytab,krb5_ticket ** ticket)65 krb5_recvauth_match_version(krb5_context context,
66 krb5_auth_context *auth_context,
67 krb5_pointer p_fd,
68 krb5_boolean (*match_appl_version)(const void *,
69 const char*),
70 const void *match_data,
71 krb5_principal server,
72 int32_t flags,
73 krb5_keytab keytab,
74 krb5_ticket **ticket)
75 {
76 krb5_error_code ret;
77 const char *version = KRB5_SENDAUTH_VERSION;
78 char her_version[sizeof(KRB5_SENDAUTH_VERSION)];
79 char *her_appl_version;
80 uint32_t len;
81 u_char repl;
82 krb5_data data;
83 krb5_flags ap_options;
84 ssize_t n;
85
86 /*
87 * If there are no addresses in auth_context, get them from `fd'.
88 */
89
90 if (*auth_context == NULL) {
91 ret = krb5_auth_con_init (context, auth_context);
92 if (ret)
93 return ret;
94 }
95
96 ret = krb5_auth_con_setaddrs_from_fd (context,
97 *auth_context,
98 p_fd);
99 if (ret)
100 return ret;
101
102 if(!(flags & KRB5_RECVAUTH_IGNORE_VERSION)) {
103 n = krb5_net_read (context, p_fd, &len, 4);
104 if (n < 0) {
105 ret = errno;
106 krb5_set_error_message(context, ret, "read: %s", strerror(ret));
107 return ret;
108 }
109 if (n == 0) {
110 krb5_set_error_message(context, KRB5_SENDAUTH_BADAUTHVERS,
111 N_("Failed to receive sendauth data", ""));
112 return KRB5_SENDAUTH_BADAUTHVERS;
113 }
114 len = ntohl(len);
115 if (len != sizeof(her_version)
116 || krb5_net_read (context, p_fd, her_version, len) != len
117 || strncmp (version, her_version, len)) {
118 repl = 1;
119 krb5_net_write (context, p_fd, &repl, 1);
120 krb5_clear_error_message (context);
121 return KRB5_SENDAUTH_BADAUTHVERS;
122 }
123 }
124
125 n = krb5_net_read (context, p_fd, &len, 4);
126 if (n < 0) {
127 ret = errno;
128 krb5_set_error_message(context, ret, "read: %s", strerror(ret));
129 return ret;
130 }
131 if (n == 0) {
132 krb5_clear_error_message (context);
133 return KRB5_SENDAUTH_BADAPPLVERS;
134 }
135 len = ntohl(len);
136 her_appl_version = malloc (len);
137 if (her_appl_version == NULL) {
138 repl = 2;
139 krb5_net_write (context, p_fd, &repl, 1);
140 krb5_set_error_message(context, ENOMEM,
141 N_("malloc: out of memory", ""));
142 return ENOMEM;
143 }
144 if (krb5_net_read (context, p_fd, her_appl_version, len) != len
145 || !(*match_appl_version)(match_data, her_appl_version)) {
146 repl = 2;
147 krb5_net_write (context, p_fd, &repl, 1);
148 krb5_set_error_message(context, KRB5_SENDAUTH_BADAPPLVERS,
149 N_("wrong sendauth version (%s)", ""),
150 her_appl_version);
151 free (her_appl_version);
152 return KRB5_SENDAUTH_BADAPPLVERS;
153 }
154 free (her_appl_version);
155
156 repl = 0;
157 if (krb5_net_write (context, p_fd, &repl, 1) != 1) {
158 ret = errno;
159 krb5_set_error_message(context, ret, "write: %s", strerror(ret));
160 return ret;
161 }
162
163 krb5_data_zero (&data);
164 ret = krb5_read_message (context, p_fd, &data);
165 if (ret)
166 return ret;
167
168 ret = krb5_rd_req (context,
169 auth_context,
170 &data,
171 server,
172 keytab,
173 &ap_options,
174 ticket);
175 krb5_data_free (&data);
176 if (ret) {
177 krb5_data error_data;
178 krb5_error_code ret2;
179
180 ret2 = krb5_mk_error (context,
181 ret,
182 NULL,
183 NULL,
184 NULL,
185 server,
186 NULL,
187 NULL,
188 &error_data);
189 if (ret2 == 0) {
190 krb5_write_message (context, p_fd, &error_data);
191 krb5_data_free (&error_data);
192 }
193 return ret;
194 }
195
196 len = 0;
197 if (krb5_net_write (context, p_fd, &len, 4) != 4) {
198 ret = errno;
199 krb5_set_error_message(context, ret, "write: %s", strerror(ret));
200 krb5_free_ticket(context, *ticket);
201 *ticket = NULL;
202 return ret;
203 }
204
205 if (ap_options & AP_OPTS_MUTUAL_REQUIRED) {
206 ret = krb5_mk_rep (context, *auth_context, &data);
207 if (ret) {
208 krb5_free_ticket(context, *ticket);
209 *ticket = NULL;
210 return ret;
211 }
212
213 ret = krb5_write_message (context, p_fd, &data);
214 if (ret) {
215 krb5_free_ticket(context, *ticket);
216 *ticket = NULL;
217 return ret;
218 }
219 krb5_data_free (&data);
220 }
221 return 0;
222 }
223