]> andersk Git - moira.git/blob - update/send_file.c
Build without krb4 if it's unavailable.
[moira.git] / update / send_file.c
1 /* $Id$
2  *
3  * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
4  * For copying and distribution information, please see the file
5  * <mit-copyright.h>.
6  */
7
8 #include <mit-copyright.h>
9 #include <moira.h>
10 #include "update_server.h"
11
12 #include <sys/stat.h>
13
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19
20 #ifdef HAVE_KRB4
21 #include <des.h>
22 #endif
23 #include <update.h>
24
25 RCSID("$Header$");
26
27 #ifdef HAVE_KRB4
28 extern des_cblock session;
29 #endif
30
31 /*
32  * syntax:
33  * (already sent) pathname file_size checksum
34  * <<< (int)code                        can we send it?
35  * >>> data
36  * <<< 0
37  * >>> data
38  * <<< 0
39  * ....
40  * >>> data                             (last block)
41  * <<< 0        (on final write, close, sync, checksum)
42  *
43  * returns:
44  *  0 on success
45  *  1 on error (file not found, etc)
46  */
47
48 int mr_send_file(int conn, char *pathname, char *target_path, int encrypt)
49 {
50   int n, fd, code, n_to_send, i;
51   char data[UPDATE_BUFSIZ], enc[UPDATE_BUFSIZ];
52   long response;
53   struct stat statb;
54 #ifdef HAVE_KRB4
55   des_key_schedule sched;
56   des_cblock ivec;
57 #endif
58
59   /* send file over */
60   fd = open(pathname, O_RDONLY, 0);
61   if (fd < 0)
62     {
63       com_err(whoami, errno, "unable to open %s for read", pathname);
64       return MR_OCONFIG;
65     }
66   if (fstat(fd, &statb))
67     {
68       com_err(whoami, errno, "unable to stat %s", pathname);
69       close(fd);
70       return MR_OCONFIG;
71     }
72   n_to_send = statb.st_size;
73
74   sprintf(data, "XFER_00%c %d %d %s", (encrypt ? '3' : '2'), n_to_send,
75           checksum_file(pathname), target_path);
76   code = send_string(conn, data, strlen(data) + 1);
77   if (code)
78     {
79       com_err(whoami, code, "sending XFER request");
80       close(fd);
81       return code;
82     }
83   code = recv_int(conn, &response);
84   if (code)
85     {
86       com_err(whoami, code, "getting reply from XFER request");
87       close(fd);
88       return code;
89     }
90   if (response)
91     {
92       com_err(whoami, response, "transfer request (XFER) rejected");
93       close(fd);
94       return response;
95     }
96
97   code = recv_int(conn, &response);
98   if (code)
99     {
100       com_err(whoami, code, ": lost connection");
101       close(fd);
102       return code;
103     }
104   if (response)
105     {
106       com_err(whoami, response, " from remote server: can't update %s",
107               pathname);
108       close(fd);
109       return response;
110     }
111
112   if (encrypt)
113     {
114 #ifdef HAVE_KRB4
115       des_key_sched(session, sched);
116       memmove(ivec, session, sizeof(ivec));
117 #else
118       /* The session key only gets stored if auth happens in krb4 to
119          begin with. If you don't have krb4, you can't possibly be
120          coming up with a valid session key. */
121       return MR_NO_KRB4;
122 #endif
123     }
124
125   while (n_to_send > 0)
126     {
127       n = read(fd, data, sizeof(data));
128       if (n < 0)
129         {
130           com_err(whoami, errno, "reading %s for transmission", pathname);
131           close(fd);
132           return MR_ABORTED;
133         }
134       if (encrypt)
135         {
136 #ifdef HAVE_KRB4
137           memset(data + n, 0, sizeof(data) -n);
138           des_pcbc_encrypt(data, enc, (n + 7) & ~7, sched, ivec, 0);
139           /* save vector to continue chaining */
140           for (i = 0; i < 8; i++)
141             ivec[i] = data[n - 8 + i] ^ enc[n - 8 + i];
142           /* round up to multiple of 8 */
143           n = (n + 7) & ~7;
144           code = send_string(conn, enc, n);
145 #endif
146         }
147       else
148         code = send_string(conn, data, n);
149       if (code)
150         {
151           com_err(whoami, code, "transmitting file %s", pathname);
152           close(fd);
153           return code;
154         }
155
156       n_to_send -= n;
157       code = recv_int(conn, &response);
158       if (code)
159         {
160           com_err(whoami, code, "awaiting ACK during transmission of %s",
161                   pathname);
162           close(fd);
163           return code;
164         }
165       if (response)
166         {
167           com_err(whoami, response,
168                   "from remote server during transmission of %s",
169                   pathname);
170           close(fd);
171           return response;
172         }
173     }
174
175   if (statb.st_size == 0)
176     {
177       code = recv_int(conn, &response);
178       if (code)
179         {
180           com_err(whoami, code, "awaiting ACK after transmission of %s",
181                   pathname);
182           close(fd);
183           return code;
184         }
185       if (response)
186         {
187           com_err(whoami, response,
188                   "from remote server after transmission of %s",
189                   pathname);
190           close(fd);
191           return response;
192         }
193     }
194   close(fd);
195   return MR_SUCCESS;
196 }
This page took 0.054794 seconds and 5 git commands to generate.