source: trunk/third/moira/update/send_file.c @ 24319

Revision 24319, 4.2 KB checked in by broder, 14 years ago (diff)
New Moira snapshot from SVN.
Line 
1/* $Id: send_file.c 3956 2010-01-05 20:56:56Z zacheiss $
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
25RCSID("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/update/send_file.c $ $Id: send_file.c 3956 2010-01-05 20:56:56Z zacheiss $");
26
27#ifdef HAVE_KRB4
28extern 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
48int 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((des_cblock *)data, (des_cblock *)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}
Note: See TracBrowser for help on using the repository browser.