b862357fbd2639754d91327a896d6ff6c18bf8dd
[gnupg.git] / g10 / ks-proto.c
1 /* ks-proto.c  keyserver protocol handling
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GNUPG.
5  *
6  * GNUPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GNUPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 /****************
22  * The extended HKP protocol:
23  *
24  *  GET /pks/lookup[/<gnupg_user_id>][?[op=<cmd>][&armor=0][&search=<keywords>]]
25  *
26  * Default is: "armor=1", "op=get". "search" is only allowed if gnupg_user_id
27  * is not present.  GET maybe replaced by HEAD in which case only some status
28  * information is returned.
29  *
30  * Hmmm, I don't like it, the better solution is to use:
31  *
32  *  /pks/gnupg/get for binary lookups
33  *  /pks/gnupg/upd to update a key
34  *  /pks/gnupg/ins to insert a new key
35  *
36  * Optional a version string can be inserted as in:
37  *
38  *  /pks/gnupg/v1.0/get
39  *
40  * Returned HTTP options:
41  *  X-Key-Hash: <rmd160 hash value of the keyblock>
42  *  X-Key-MTime: <last modification time>
43  *  X-Key-LID: <local_key_id_used_for_update_etc>
44  * [fixme: is X-.... allowed?]
45  */
46
47 #include <config.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include "util.h"
52 #include "ks-proto.h"
53
54 #if 0
55 /****************
56  * Read a protocol line
57  */
58 static int
59 read_line( FILE *fp )
60 {
61     return -1;
62 }
63
64
65
66
67 /****************
68  * Send a HKP request
69  */
70 int
71 hkp_request( int operation, const char *user_id )
72 {
73
74 }
75
76
77
78
79
80 /************************************************
81  ******* client communication stuff  ************
82  ************************************************/
83
84 /****************
85  * Initialisieren des clients
86  * Es wird ein Handle zurückgegeben oder -1 bei einem fehler.
87  * z.Z. ist nut eine Verbindung gleichzeitig möglich.
88  * Wenn einer serverpid von 0 angegeben wird, so wird diese
89  * der environment  variabeln ATEXDB_PID entnommen.
90  */
91
92 int
93 hkp_open( const char *serverurl )
94 {
95     const char *s;
96
97     s = SERVER_NAME_TEMPLATE;
98     client.serv_name = xmalloc(strlen(s) + 10 );
99     sprintf(client.serv_name,s, serverpid );
100     if( opt.verbose )
101         Info("Using unix domain stream '%s'", client.serv_name );
102
103     memset( &client.serv_addr, 0, sizeof client.serv_addr );
104     client.serv_addr.sun_family = AF_UNIX;
105     strcpy( client.serv_addr.sun_path, client.serv_name );
106     client.serv_addr_len = strlen(client.serv_addr.sun_path)
107                             + sizeof client.serv_addr.sun_family;
108
109     client.sockfd = -1;
110     if( DoCheckVersion() )
111         return -1;
112     return 0;
113 }
114
115
116 static int
117 DoConnect()
118 {
119     if( client.sockfd != -1 )
120         DoDisconnect();
121     if( (client.sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) {
122         Error(1000,"can't open unix domain socket");
123         return 1;
124     }
125     if( connect(client.sockfd, (struct sockaddr*)&client.serv_addr,
126                                 client.serv_addr_len) == -1 ) {
127         Error(1000,"can't connect to '%s'",client.serv_addr.sun_path);
128         return 1;
129     }
130
131     return 0; /* okay */
132 }
133
134 static int
135 DoDisconnect()
136 {
137     if( client.sockfd != -1 ) {
138         close(client.sockfd);
139         client.sockfd = -1;
140     }
141     return 0; /* okay */
142 }
143
144 /****************
145  * NBYTES auf den aktuellen stream schreiben.
146  */
147 static int
148 DoWrite( void *buf, size_t nbytes )
149 {
150     size_t nleft = nbytes;
151     ssize_t nwritten;
152
153     while( nleft > 0 ) {
154         /* FIXME: add EINTR handling */
155         nwritten = write(client.sockfd, buf, nleft);
156         if( nwritten < 0 ) {
157             Error(1000,"error writing to server");
158             return -1;
159         }
160         nleft -= nwritten;
161         buf = (char*)buf + nwritten;
162     }
163     return 0;
164 }
165
166 static int
167 DoWriteStr( const char *s )
168 {
169     return DoWrite((char *)s, strlen(s) );
170 }
171
172
173 static int
174 DoRead( void *buf, size_t buflen, size_t *ret_nread, int stop)
175 {
176     size_t nleft = buflen;
177     int nread;
178     char *p;
179
180     p = buf;
181     while( nleft > 0 ) {
182         /* FIXME: add EINTR handling */
183         nread = read(client.sockfd, buf, stop? 1 : nleft);
184         if( nread < 0 ) {
185             Error(1000,"error reading from server");
186             return -1;
187         }
188         else if( !nread )
189             break; /* EOF */
190         nleft -= nread;
191         buf = (char*)buf + nread;
192         if( stop )
193             for(; p < (char*)buf ; p++ )
194                 if( *p == '\n' )
195                     goto leave;
196     }
197   leave:
198     if( ret_nread )
199         *ret_nread = buflen - nleft;
200     return 0;
201 }
202
203 /****************
204  * Like DoRead(), but append the received data to the given strgbuf.
205  * read a maximum of nbytes;
206  */
207 static int
208 DoReadIntoStrgbuf( strgbuf_t *strgbuf, size_t nbytes, size_t *ret_nread)
209 {
210     size_t ntotal, nleft;
211     int nread;
212     byte *p, buffer[1000];
213
214     ntotal = 0;
215     nleft = nbytes;
216     while( nleft ) {
217         nread = read(client.sockfd, buffer,
218                             nleft > DIM(buffer)? DIM(buffer) : nleft);
219         if( nread < 0 ) {
220             Error(1000,"error reading from server");
221             return -1;
222         }
223         else if( !nread )
224             break; /* EOF */
225         nleft -= nread;
226         ntotal += nread;
227         /* ab in den stringbuffer */
228         for(p=buffer; nread; nread--, p++ )
229             PutStrgbuf(strgbuf, *p );
230     }
231
232     if( ret_nread )
233         *ret_nread = ntotal;
234     return 0;
235 }
236
237
238 /****************
239  * In retval wird das numerische argument nach OK zurückgegeben
240  */
241 static int
242 DoRequest( char *request, long *retval )
243 {
244     if( DoWrite(request, strlen(request)) )
245         return -1;
246     return DoWaitReply( retval );
247 }
248
249 static int
250 DoWaitReply( long *retval )
251 {
252     char *p, buf[200]; /* enough room for messages */
253     size_t nread;
254
255     /* read but stop at the first newline */
256     if( DoRead(buf, DIM(buf)-2, &nread, 1 ) )
257         return -1;
258     buf[DIM(buf)-1] = 0;
259     /* fixme: should check, that we have the linefeed and otherwise
260      * perform a dummy read */
261     if( p = strchr(buf, '\n') )
262         *p = 0;
263     if( *buf == 'O' && buf[1] == 'K' && (buf[2]==' ' || !buf[2]) ) {
264         if( retval )
265             *retval = buf[2]? strtol(buf+3, NULL, 10 ):0;
266         return 0;
267     }
268     Error(0, "Server replied: %.60s", buf );
269     return -1;
270 }
271
272
273
274
275
276
277
278
279
280
281
282
283 #endif
284
285
286