1*1c9681d1Schristos /*	$NetBSD: store_sock.c,v 1.2 2017/01/28 21:31:49 christos Exp $	*/
2e0895134Schristos 
3e0895134Schristos /*
4e0895134Schristos  * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
5e0895134Schristos  * (Royal Institute of Technology, Stockholm, Sweden).
6e0895134Schristos  * All rights reserved.
7e0895134Schristos  *
8e0895134Schristos  * Redistribution and use in source and binary forms, with or without
9e0895134Schristos  * modification, are permitted provided that the following conditions
10e0895134Schristos  * are met:
11e0895134Schristos  *
12e0895134Schristos  * 1. Redistributions of source code must retain the above copyright
13e0895134Schristos  *    notice, this list of conditions and the following disclaimer.
14e0895134Schristos  *
15e0895134Schristos  * 2. Redistributions in binary form must reproduce the above copyright
16e0895134Schristos  *    notice, this list of conditions and the following disclaimer in the
17e0895134Schristos  *    documentation and/or other materials provided with the distribution.
18e0895134Schristos  *
19e0895134Schristos  * 3. Neither the name of the Institute nor the names of its contributors
20e0895134Schristos  *    may be used to endorse or promote products derived from this software
21e0895134Schristos  *    without specific prior written permission.
22e0895134Schristos  *
23e0895134Schristos  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24e0895134Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25e0895134Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26e0895134Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27e0895134Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28e0895134Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29e0895134Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30e0895134Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31e0895134Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32e0895134Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33e0895134Schristos  * SUCH DAMAGE.
34e0895134Schristos  */
35e0895134Schristos 
36e0895134Schristos #include "krb5_locl.h"
37e0895134Schristos #include "store-int.h"
38e0895134Schristos 
39e0895134Schristos #ifdef _WIN32
40e0895134Schristos #include <winsock2.h>
41e0895134Schristos #endif
42e0895134Schristos 
43e0895134Schristos typedef struct socket_storage {
44e0895134Schristos     krb5_socket_t sock;
45e0895134Schristos } socket_storage;
46e0895134Schristos 
47e0895134Schristos #define SOCK(S) (((socket_storage*)(S)->data)->sock)
48e0895134Schristos 
49e0895134Schristos static ssize_t
socket_fetch(krb5_storage * sp,void * data,size_t size)50e0895134Schristos socket_fetch(krb5_storage * sp, void *data, size_t size)
51e0895134Schristos {
52e0895134Schristos     return net_read(SOCK(sp), data, size);
53e0895134Schristos }
54e0895134Schristos 
55e0895134Schristos static ssize_t
socket_store(krb5_storage * sp,const void * data,size_t size)56e0895134Schristos socket_store(krb5_storage * sp, const void *data, size_t size)
57e0895134Schristos {
58e0895134Schristos     return net_write(SOCK(sp), data, size);
59e0895134Schristos }
60e0895134Schristos 
61e0895134Schristos static off_t
socket_seek(krb5_storage * sp,off_t offset,int whence)62e0895134Schristos socket_seek(krb5_storage * sp, off_t offset, int whence)
63e0895134Schristos {
64e0895134Schristos     return lseek(SOCK(sp), offset, whence);
65e0895134Schristos }
66e0895134Schristos 
67e0895134Schristos static int
socket_trunc(krb5_storage * sp,off_t offset)68e0895134Schristos socket_trunc(krb5_storage * sp, off_t offset)
69e0895134Schristos {
70e0895134Schristos     if (ftruncate(SOCK(sp), offset) == -1)
71e0895134Schristos 	return errno;
72e0895134Schristos     return 0;
73e0895134Schristos }
74e0895134Schristos 
75e0895134Schristos static int
socket_sync(krb5_storage * sp)76e0895134Schristos socket_sync(krb5_storage * sp)
77e0895134Schristos {
78e0895134Schristos     if (fsync(SOCK(sp)) == -1)
79e0895134Schristos 	return errno;
80e0895134Schristos     return 0;
81e0895134Schristos }
82e0895134Schristos 
83e0895134Schristos static void
socket_free(krb5_storage * sp)84e0895134Schristos socket_free(krb5_storage * sp)
85e0895134Schristos {
86e0895134Schristos     int save_errno = errno;
87e0895134Schristos     if (rk_IS_SOCKET_ERROR(rk_closesocket(SOCK(sp))))
88e0895134Schristos         errno = rk_SOCK_ERRNO;
89e0895134Schristos     else
90e0895134Schristos         errno = save_errno;
91e0895134Schristos }
92e0895134Schristos 
93e0895134Schristos /**
94e0895134Schristos  *
95e0895134Schristos  *
96e0895134Schristos  * @return A krb5_storage on success, or NULL on out of memory error.
97e0895134Schristos  *
98e0895134Schristos  * @ingroup krb5_storage
99e0895134Schristos  *
100e0895134Schristos  * @sa krb5_storage_emem()
101e0895134Schristos  * @sa krb5_storage_from_mem()
102e0895134Schristos  * @sa krb5_storage_from_readonly_mem()
103e0895134Schristos  * @sa krb5_storage_from_data()
104e0895134Schristos  * @sa krb5_storage_from_fd()
105e0895134Schristos  */
106e0895134Schristos 
107e0895134Schristos KRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL
krb5_storage_from_socket(krb5_socket_t sock_in)108e0895134Schristos krb5_storage_from_socket(krb5_socket_t sock_in)
109e0895134Schristos {
110e0895134Schristos     krb5_storage *sp;
111e0895134Schristos     int saved_errno;
112e0895134Schristos     krb5_socket_t sock;
113e0895134Schristos 
114e0895134Schristos #ifdef _WIN32
115e0895134Schristos     WSAPROTOCOL_INFO info;
116e0895134Schristos 
117e0895134Schristos     if (WSADuplicateSocket(sock_in, GetCurrentProcessId(), &info) == 0)
118e0895134Schristos     {
119e0895134Schristos 
120e0895134Schristos 	sock = WSASocket( FROM_PROTOCOL_INFO,
121e0895134Schristos 			  FROM_PROTOCOL_INFO,
122e0895134Schristos 			  FROM_PROTOCOL_INFO,
123e0895134Schristos 			  &info, 0, 0);
124e0895134Schristos     }
125e0895134Schristos #else
126e0895134Schristos     sock = dup(sock_in);
127e0895134Schristos #endif
128e0895134Schristos 
129e0895134Schristos     if (sock == rk_INVALID_SOCKET)
130e0895134Schristos 	return NULL;
131e0895134Schristos 
132e0895134Schristos     errno = ENOMEM;
133e0895134Schristos     sp = malloc(sizeof(krb5_storage));
134e0895134Schristos     if (sp == NULL) {
135e0895134Schristos 	saved_errno = errno;
136e0895134Schristos 	rk_closesocket(sock);
137e0895134Schristos 	errno = saved_errno;
138e0895134Schristos 	return NULL;
139e0895134Schristos     }
140e0895134Schristos 
141e0895134Schristos     errno = ENOMEM;
142e0895134Schristos     sp->data = malloc(sizeof(socket_storage));
143e0895134Schristos     if (sp->data == NULL) {
144e0895134Schristos 	saved_errno = errno;
145e0895134Schristos 	rk_closesocket(sock);
146e0895134Schristos 	free(sp);
147e0895134Schristos 	errno = saved_errno;
148e0895134Schristos 	return NULL;
149e0895134Schristos     }
150e0895134Schristos     sp->flags = 0;
151e0895134Schristos     sp->eof_code = HEIM_ERR_EOF;
152e0895134Schristos     SOCK(sp) = sock;
153e0895134Schristos     sp->fetch = socket_fetch;
154e0895134Schristos     sp->store = socket_store;
155e0895134Schristos     sp->seek = socket_seek;
156e0895134Schristos     sp->trunc = socket_trunc;
157e0895134Schristos     sp->fsync = socket_sync;
158e0895134Schristos     sp->free = socket_free;
159e0895134Schristos     sp->max_alloc = UINT_MAX/8;
160e0895134Schristos     return sp;
161e0895134Schristos }
162