Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / rpc / sec / authdesubr.c
blobdf71d0a491c8003b19c5fa68a860a61f600f8aa7
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2014 Gary Mills
24 * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 * Copyright (c) 2018, Joyent, Inc.
29 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
33 * Portions of this source code were derived from Berkeley 4.3 BSD
34 * under license from the Regents of the University of California.
38 * Miscellaneous support routines for kernel implentation of AUTH_DES
42 * rtime - get time from remote machine
44 * sets time, obtaining value from host
45 * on the udp/time socket. Since timeserver returns
46 * with time of day in seconds since Jan 1, 1900, must
47 * subtract 86400(365*70 + 17) to get time
48 * since Jan 1, 1970, which is what get/settimeofday
49 * uses.
51 #include <sys/param.h>
52 #include <sys/types.h>
53 #include <sys/time.h>
54 #include <sys/systm.h>
55 #include <sys/errno.h>
56 #include <sys/proc.h>
57 #include <sys/user.h>
58 #include <sys/socket.h>
59 #include <sys/sysmacros.h>
60 #include <netinet/in.h>
61 #include <rpc/rpc.h>
62 #include <sys/stream.h>
63 #include <sys/strsubr.h>
64 #include <sys/cred.h>
65 #include <sys/utsname.h>
66 #include <sys/vnode.h>
67 #include <sys/file.h>
68 #include <sys/uio.h>
69 #include <sys/systeminfo.h>
70 #include <rpc/rpcb_prot.h>
71 #include <sys/cmn_err.h>
73 #define TOFFSET ((uint32_t)86400 * (365 * 70 + (70 / 4)))
74 #define WRITTEN ((uint32_t)86400 * (365 * 86 + (86 / 4)))
76 #define NC_INET "inet" /* XXX */
78 int
79 rtime(struct knetconfig *synconfig, struct netbuf *addrp, int calltype,
80 struct timeval *timep, struct timeval *wait)
82 int error;
83 int timo;
84 time_t thetime;
85 int32_t srvtime;
86 uint32_t dummy;
87 struct t_kunitdata *unitdata;
88 struct t_call *server;
89 TIUSER *tiptr;
90 int type;
91 int uderr;
92 int i;
93 int retries;
94 mblk_t *mp;
95 mblk_t *mp2;
97 retries = 5;
98 if (calltype == 0) {
99 again:
100 RPCLOG0(8, "rtime: using old method\n");
101 if ((error = t_kopen(NULL, synconfig->knc_rdev,
102 FREAD|FWRITE, &tiptr, CRED())) != 0) {
103 RPCLOG(1, "rtime: t_kopen %d\n", error);
104 return (-1);
107 if ((error = t_kbind(tiptr, NULL, NULL)) != 0) {
108 (void) t_kclose(tiptr, 1);
109 RPCLOG(1, "rtime: t_kbind %d\n", error);
110 return (-1);
113 if (synconfig->knc_semantics == NC_TPI_CLTS) {
114 if ((error = t_kalloc(tiptr, T_UNITDATA,
115 T_UDATA|T_ADDR, (char **)&unitdata)) != 0) {
116 RPCLOG(1, "rtime: t_kalloc %d\n", error);
117 (void) t_kclose(tiptr, 1);
118 return (-1);
121 unitdata->addr.len = addrp->len;
122 bcopy(addrp->buf, unitdata->addr.buf,
123 unitdata->addr.len);
125 dummy = 0;
126 unitdata->udata.buf = (caddr_t)&dummy;
127 unitdata->udata.len = sizeof (dummy);
129 if ((error = t_ksndudata(tiptr, unitdata, NULL)) !=
130 0) {
131 RPCLOG(1, "rtime: t_ksndudata %d\n", error);
132 (void) t_kfree(tiptr, (char *)unitdata,
133 T_UNITDATA);
134 (void) t_kclose(tiptr, 1);
135 return (-1);
138 timo = TIMEVAL_TO_TICK(wait);
140 RPCLOG(8, "rtime: timo %x\n", timo);
141 if ((error = t_kspoll(tiptr, timo, READWAIT,
142 &type)) != 0) {
143 RPCLOG(1, "rtime: t_kspoll %d\n", error);
144 (void) t_kfree(tiptr, (char *)unitdata,
145 T_UNITDATA);
146 (void) t_kclose(tiptr, 1);
147 return (-1);
150 if (type == 0) {
151 RPCLOG0(1, "rtime: t_kspoll timed out\n");
152 (void) t_kfree(tiptr, (char *)unitdata,
153 T_UNITDATA);
154 (void) t_kclose(tiptr, 1);
155 return (-1);
158 error = t_krcvudata(tiptr, unitdata, &type, &uderr);
159 if (error != 0) {
160 RPCLOG(1, "rtime: t_krcvudata %d\n", error);
161 (void) t_kfree(tiptr, (char *)unitdata,
162 T_UNITDATA);
163 (void) t_kclose(tiptr, 1);
164 if (error == EBADMSG && retries-- > 0)
165 goto again;
166 return (-1);
169 if (type == T_UDERR) {
170 if (bcmp(addrp->buf, unitdata->addr.buf,
171 unitdata->addr.len) != 0) {
173 * Response comes from some other
174 * destination:
175 * ignore it since it's not related to the
176 * request we just sent out.
178 (void) t_kfree(tiptr, (char *)unitdata,
179 T_UNITDATA);
180 (void) t_kclose(tiptr, 1);
181 goto again;
185 if (type != T_DATA) {
186 RPCLOG(1,
187 "rtime: t_krcvudata returned type %d\n",
188 type);
189 (void) t_kfree(tiptr, (char *)unitdata,
190 T_UNITDATA);
191 (void) t_kclose(tiptr, 1);
192 if (retries-- == 0)
193 return (-1);
194 goto again;
197 if (unitdata->udata.len < sizeof (uint32_t)) {
198 RPCLOG(1, "rtime: bad rcvd length %d\n",
199 unitdata->udata.len);
200 (void) t_kfree(tiptr, (char *)unitdata,
201 T_UNITDATA);
202 (void) t_kclose(tiptr, 1);
203 if (retries-- == 0)
204 return (-1);
205 goto again;
208 thetime = (time_t)ntohl(
209 /* LINTED pointer alignment */
210 *(uint32_t *)unitdata->udata.buf);
211 (void) t_kfree(tiptr, (char *)unitdata, T_UNITDATA);
213 } else {
215 if ((error = t_kalloc(tiptr, T_CALL, T_ADDR,
216 (char **)&server)) != 0) {
217 RPCLOG(1, "rtime: t_kalloc %d\n", error);
218 (void) t_kclose(tiptr, 1);
219 return (-1);
222 server->addr.len = addrp->len;
223 bcopy(addrp->buf, server->addr.buf, server->addr.len);
225 if ((error = t_kconnect(tiptr, server, NULL)) != 0) {
226 RPCLOG(1, "rtime: t_kconnect %d\n", error);
227 (void) t_kfree(tiptr, (char *)server, T_CALL);
228 (void) t_kclose(tiptr, 1);
229 return (-1);
231 (void) t_kfree(tiptr, (char *)server, T_CALL);
233 timo = TIMEVAL_TO_TICK(wait);
235 RPCLOG(8, "rtime: timo %x\n", timo);
237 i = 0;
238 dummy = 0;
240 /* now read up to 4 bytes from the TIME server */
241 while (i < sizeof (dummy)) {
243 error = t_kspoll(tiptr, timo, READWAIT, &type);
244 if (error != 0) {
245 RPCLOG(1, "rtime: t_kspoll %d\n",
246 error);
247 (void) t_kclose(tiptr, 1);
248 return (-1);
251 if (type == 0) {
252 RPCLOG0(1,
253 "rtime: t_kspoll timed out\n");
254 (void) t_kclose(tiptr, 1);
255 return (-1);
258 error = tli_recv(tiptr, &mp,
259 tiptr->fp->f_flag);
260 if (error != 0) {
261 RPCLOG(1, "rtime: tli_recv %d\n",
262 error);
263 (void) t_kclose(tiptr, 1);
264 return (-1);
267 if (mp->b_datap->db_type != M_DATA) {
268 RPCLOG(1, "rtime: wrong msg type %d\n",
269 mp->b_datap->db_type);
270 RPCLOG(1,
271 "rtime: wrong msg type: read %d"
272 " bytes\n", i);
273 (void) t_kclose(tiptr, 1);
274 freemsg(mp);
275 return (-1);
278 mp2 = mp;
281 * The outer loop iterates until we reach the
282 * end of the mblk chain.
284 while (mp2 != NULL) {
287 * The inner loop iterates until
288 * we've gotten 4 bytes or until
289 * the mblk is exhausted.
291 while (i < sizeof (dummy) &&
292 mp2->b_rptr < mp2->b_wptr) {
294 i++;
297 * We avoid big-endian/little-endian
298 * issues by serializing the result
299 * one byte at a time.
301 dummy <<= 8;
302 dummy += ((*mp2->b_rptr) &
303 0xFF);
305 mp2->b_rptr++;
308 mp2 = mp2->b_cont;
311 freemsg(mp);
314 thetime = (time_t)dummy;
317 (void) t_kclose(tiptr, 1);
319 } else {
320 CLIENT *client;
321 struct timeval timout;
323 RPCLOG0(8, "rtime: using new method\n");
325 new_again:
327 * We talk to rpcbind.
329 error = clnt_tli_kcreate(synconfig, addrp, (rpcprog_t)RPCBPROG,
330 (rpcvers_t)RPCBVERS, 0, retries, CRED(), &client);
332 if (error != 0) {
333 RPCLOG(1,
334 "rtime: clnt_tli_kcreate returned %d\n", error);
335 return (-1);
337 timout.tv_sec = 60;
338 timout.tv_usec = 0;
339 error = clnt_call(client, RPCBPROC_GETTIME, (xdrproc_t)xdr_void,
340 NULL, (xdrproc_t)xdr_u_int,
341 (caddr_t)&srvtime, timout);
342 thetime = srvtime;
343 auth_destroy(client->cl_auth);
344 clnt_destroy(client);
345 if (error == RPC_UDERROR) {
346 if (retries-- > 0)
347 goto new_again;
349 if (error != RPC_SUCCESS) {
350 RPCLOG(1, "rtime: time sync clnt_call returned %d\n",
351 error);
352 error = EIO;
353 return (-1);
357 if (calltype != 0)
358 thetime += TOFFSET;
360 RPCLOG(8, "rtime: thetime = %lx\n", thetime);
362 if (thetime < WRITTEN) {
363 RPCLOG(1, "rtime: time returned is too far in past %lx",
364 thetime);
365 RPCLOG(1, "rtime: WRITTEN %x", WRITTEN);
366 return (-1);
368 thetime -= TOFFSET;
370 timep->tv_sec = thetime;
371 RPCLOG(8, "rtime: timep->tv_sec = %lx\n", timep->tv_sec);
372 RPCLOG(8, "rtime: machine time = %lx\n", gethrestime_sec());
373 timep->tv_usec = 0;
374 RPCLOG0(8, "rtime: returning success\n");
375 return (0);
379 * What is my network name?
380 * WARNING: this gets the network name in sun unix format.
381 * Other operating systems (non-unix) are free to put something else
382 * here.
384 * Return 0 on success
385 * Return RPC errors (non-zero values) if failed.
387 enum clnt_stat
388 kgetnetname(char *netname)
390 return (key_getnetname(netname, CRED()));