OPENAFS-SA-2016-002 AFSStoreStatus information leak
[openafs.git] / src / libafscp / afscp_file.c
1 /* AUTORIGHTS
2 Copyright (C) 2003 - 2010 Chaskiel Grundman
3 All rights reserved
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11
12 2. Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <afsconfig.h>
28 #include <afs/param.h>
29
30 #include <roken.h>
31
32 #include <afs/vlserver.h>
33 #include <afs/vldbint.h>
34 #include "afscp.h"
35 #include "afscp_internal.h"
36
37 /* this is not yet 64-bit clean */
38 ssize_t
39 afscp_PRead(const struct afscp_venusfid * fid, void *buffer,
40             size_t count, off_t offset)
41 {
42     struct AFSFetchStatus fst;
43     struct AFSVolSync vs;
44     struct AFSCallBack cb;
45     struct AFSFid tf = fid->fid;
46     struct afscp_volume *vol;
47     struct afscp_server *server;
48     struct rx_call *c = NULL;
49     int code;
50     int i, j, bytes, totalbytes = 0;
51     int bytesremaining;
52     char *p;
53     time_t now;
54
55     vol = afscp_VolumeById(fid->cell, fid->fid.Volume);
56     if (vol == NULL) {
57         afscp_errno = ENOENT;
58         return -1;
59     }
60     code = ENOENT;
61     for (i = 0; i < vol->nservers; i++) {
62         server = afscp_ServerByIndex(vol->servers[i]);
63         if (server && server->naddrs > 0) {
64             for (j = 0; j < server->naddrs; j++) {
65                 c = rx_NewCall(server->conns[j]);
66                 if (c != 0) {
67                     p = buffer;
68                     code = StartRXAFS_FetchData(c, &tf, offset, count);
69                     if (code != 0) {
70                         code = rx_EndCall(c, code);
71                         continue;
72                     }
73                     bytes =
74                         rx_Read(c, (char *)&bytesremaining,
75                                 sizeof(afs_int32));
76                     if (bytes != sizeof(afs_int32)) {
77                         code = rx_EndCall(c, RX_PROTOCOL_ERROR);
78                         continue;
79                     }
80                     bytesremaining = ntohl(bytesremaining);
81                     totalbytes = 0;
82                     while (bytesremaining > 0) {
83                         bytes = rx_Read(c, p, bytesremaining);
84                         if (bytes <= 0)
85                             break;
86                         p += bytes;
87                         totalbytes += bytes;
88                         bytesremaining -= bytes;
89                     }
90                     if (bytesremaining == 0) {
91                         time(&now);
92                         code = EndRXAFS_FetchData(c, &fst, &cb, &vs);
93                         if (code == 0)
94                             afscp_AddCallBack(server, &fid->fid, &fst, &cb,
95                                               now);
96                     }
97                     code = rx_EndCall(c, code);
98                 }
99                 if (code == 0) {
100                     return totalbytes;
101                 }
102             }
103         }
104     }
105     afscp_errno = code;
106     return -1;
107 }
108
109 /* this is not yet 64-bit clean */
110 ssize_t
111 afscp_PWrite(const struct afscp_venusfid * fid, const void *buffer,
112              size_t count, off_t offset)
113 {
114     struct AFSFetchStatus fst;
115     struct AFSStoreStatus sst;
116     struct AFSVolSync vs;
117     struct AFSCallBack cb;
118     struct AFSFid tf = fid->fid;
119     struct afscp_volume *vol;
120     struct afscp_server *server;
121     struct rx_call *c = NULL;
122     int code;
123     int i, j, bytes, totalbytes = 0;
124     int bytesremaining;
125     const char *p;
126     off_t filesize;
127     time_t now;
128
129     memset(&sst, 0, sizeof(sst));
130     vol = afscp_VolumeById(fid->cell, fid->fid.Volume);
131     if (vol == NULL) {
132         afscp_errno = ENOENT;
133         return -1;
134     }
135     if (vol->voltype != RWVOL) {
136         afscp_errno = EROFS;
137         return -1;
138     }
139
140     code = ENOENT;
141     for (i = 0; i < vol->nservers; i++) {
142         server = afscp_ServerByIndex(vol->servers[i]);
143         if (server && server->naddrs > 0) {
144             for (j = 0; j < server->naddrs; j++) {
145                 code =
146                     RXAFS_FetchStatus(server->conns[j], &tf, &fst, &cb, &vs);
147                 if (code != 0)
148                     continue;
149                 sst.Mask = AFS_SETMODTIME;
150                 time(&now);
151                 sst.ClientModTime = now;
152                 filesize = fst.Length;
153                 if (offset + count > filesize)
154                     filesize = offset + count;
155                 c = rx_NewCall(server->conns[j]);
156                 if (c != 0) {
157                     p = buffer;
158                     code =
159                         StartRXAFS_StoreData(c, &tf, &sst, offset, count,
160                                              filesize);
161                     if (code != 0) {
162                         code = rx_EndCall(c, code);
163                         continue;
164                     }
165                     bytesremaining = count;
166                     totalbytes = 0;
167                     while (bytesremaining > 0) {
168                         bytes = rx_Write(c, (char *)p, bytesremaining);
169                         if (bytes <= 0)
170                             break;
171                         p += bytes;
172                         totalbytes += bytes;
173                         bytesremaining -= bytes;
174                     }
175                     if (bytesremaining == 0) {
176                         code = EndRXAFS_StoreData(c, &fst, &vs);
177                     }
178                     code = rx_EndCall(c, code);
179                 }
180                 if (code == 0) {
181                     return totalbytes;
182                 }
183             }
184         }
185     }
186     afscp_errno = code;
187     return -1;
188 }