etc/services - sync with NetBSD-8
[minix.git] / crypto / external / bsd / heimdal / dist / lib / krb5 / recvauth.c
blob615820a63f9c7485ea7d78e76fd641f0d9c372a3
1 /* $NetBSD: recvauth.c,v 1.1.1.1 2011/04/13 18:15:37 elric Exp $ */
3 /*
4 * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
36 #include "krb5_locl.h"
39 * See `sendauth.c' for the format.
42 static krb5_boolean
43 match_exact(const void *data, const char *appl_version)
45 return strcmp(data, appl_version) == 0;
48 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
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)
58 return krb5_recvauth_match_version(context, auth_context, p_fd,
59 match_exact, appl_version,
60 server, flags,
61 keytab, ticket);
64 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
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)
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;
87 * If there are no addresses in auth_context, get them from `fd'.
90 if (*auth_context == NULL) {
91 ret = krb5_auth_con_init (context, auth_context);
92 if (ret)
93 return ret;
96 ret = krb5_auth_con_setaddrs_from_fd (context,
97 *auth_context,
98 p_fd);
99 if (ret)
100 return ret;
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;
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;
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;
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;
131 if (n == 0) {
132 krb5_clear_error_message (context);
133 return KRB5_SENDAUTH_BADAPPLVERS;
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;
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;
154 free (her_appl_version);
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;
163 krb5_data_zero (&data);
164 ret = krb5_read_message (context, p_fd, &data);
165 if (ret)
166 return ret;
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;
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);
193 return ret;
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;
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;
213 ret = krb5_write_message (context, p_fd, &data);
214 if (ret) {
215 krb5_free_ticket(context, *ticket);
216 *ticket = NULL;
217 return ret;
219 krb5_data_free (&data);
221 return 0;