diff options
Diffstat (limited to 'dirmngr')
-rw-r--r-- | dirmngr/ChangeLog | 23 | ||||
-rw-r--r-- | dirmngr/Makefile.am | 4 | ||||
-rw-r--r-- | dirmngr/b64dec.c | 217 | ||||
-rw-r--r-- | dirmngr/b64enc.c | 213 | ||||
-rw-r--r-- | dirmngr/cdblib.c | 54 | ||||
-rw-r--r-- | dirmngr/certcache.c | 8 | ||||
-rw-r--r-- | dirmngr/crlcache.c | 237 | ||||
-rw-r--r-- | dirmngr/crlcache.h | 2 | ||||
-rw-r--r-- | dirmngr/crlfetch.c | 3 | ||||
-rw-r--r-- | dirmngr/dirmngr-client.c | 2 | ||||
-rw-r--r-- | dirmngr/dirmngr-err.h | 12 | ||||
-rw-r--r-- | dirmngr/dirmngr.c | 95 | ||||
-rw-r--r-- | dirmngr/dirmngr.h | 6 | ||||
-rw-r--r-- | dirmngr/dirmngr_ldap.c | 24 | ||||
-rw-r--r-- | dirmngr/http.c | 1863 | ||||
-rw-r--r-- | dirmngr/http.h | 109 | ||||
-rw-r--r-- | dirmngr/ocsp.c | 6 | ||||
-rw-r--r-- | dirmngr/server.c | 2 |
18 files changed, 270 insertions, 2610 deletions
diff --git a/dirmngr/ChangeLog b/dirmngr/ChangeLog index c6db553de..c95a2f2d6 100644 --- a/dirmngr/ChangeLog +++ b/dirmngr/ChangeLog @@ -1,3 +1,26 @@ +2010-07-16 Werner Koch <[email protected]> + + * http.c, http.h: Remove. + + * dirmngr-err.h: New. + * dirmngr.h: Include dirmngr-err.h instead of gpg-error.h + + * cdblib.c: Replace assignments to ERRNO by a call to + gpg_err_set_errno. Include dirmngr-err.h. + (cdb_free) [__MINGW32CE__]: Do not use get_osfhandle. + + * dirmngr.c [!HAVE_SIGNAL_H]: Don't include signal.h. + (USE_W32_SERVICE): New. Use this to control the use of the W32 + service system. + +2010-07-06 Werner Koch <[email protected]> + + * dirmngr.c (main): Print note on directory name changes. + + Replace almost all uses of stdio by estream. + + * b64dec.c, b64enc.c: Remove. They are duplicated in ../common/. + 2010-06-28 Werner Koch <[email protected]> * dirmngr_ldap.c (my_i18n_init): Remove. diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am index 7fbff02ff..537bdf035 100644 --- a/dirmngr/Makefile.am +++ b/dirmngr/Makefile.am @@ -38,7 +38,7 @@ noinst_HEADERS = dirmngr.h crlcache.h crlfetch.h misc.h dirmngr_SOURCES = dirmngr.c dirmngr.h server.c crlcache.c crlfetch.c \ ldapserver.h ldapserver.c certcache.c certcache.h \ - b64dec.c cdb.h cdblib.c ldap.c http.c http.h misc.c \ + cdb.h cdblib.c ldap.c misc.c dirmngr-err.h \ ocsp.c ocsp.h validate.c validate.h dirmngr_LDADD = $(libcommonpth) ../gl/libgnu.a $(DNSLIBS) $(LIBASSUAN_LIBS) \ @@ -56,7 +56,7 @@ dirmngr_ldap_LDFLAGS = dirmngr_ldap_LDADD = $(libcommon) ../gl/libgnu.a $(DNSLIBS) \ $(GPG_ERROR_LIBS) $(LDAPLIBS) $(LIBINTL) $(LIBICONV) -dirmngr_client_SOURCES = dirmngr-client.c b64enc.c no-libgcrypt.c +dirmngr_client_SOURCES = dirmngr-client.c no-libgcrypt.c dirmngr_client_LDADD = $(libcommon) ../gl/libgnu.a $(LIBASSUAN_LIBS) \ $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) diff --git a/dirmngr/b64dec.c b/dirmngr/b64dec.c deleted file mode 100644 index af223aef2..000000000 --- a/dirmngr/b64dec.c +++ /dev/null @@ -1,217 +0,0 @@ -/* b64dec.c - Simple Base64 decoder. - * Copyright (C) 2008 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <assert.h> - -#include "i18n.h" -#include "util.h" - - -/* The reverse base-64 list used for base-64 decoding. */ -static unsigned char const asctobin[128] = - { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff - }; - -enum decoder_states - { - s_init, s_idle, s_lfseen, s_begin, - s_b64_0, s_b64_1, s_b64_2, s_b64_3, - s_waitendtitle, s_waitend - }; - - - -/* Initialize the context for the base64 decoder. If TITLE is NULL a - plain base64 decoding is done. If it is the empty string the - decoder will skip everything until a "-----BEGIN " line has been - seen, decoding ends at a "----END " line. - - Not yet implemented: If TITLE is either "PGP" or begins with "PGP " - the PGP armor lines are skipped as well. */ -gpg_error_t -b64dec_start (struct b64state *state, const char *title) -{ - memset (state, 0, sizeof *state); - if (title) - { - if (!strncmp (title, "PGP", 3) && (!title[3] || title[3] == ' ')) - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - - state->title = xtrystrdup (title); - if (!state->title) - return gpg_error_from_syserror (); - state->idx = s_init; - } - else - state->idx = s_b64_0; - return 0; -} - - -/* Do in-place decoding of base-64 data of LENGTH in BUFFER. Stores the - new length of the buffer at R_NBYTES. */ -gpg_error_t -b64dec_proc (struct b64state *state, void *buffer, size_t length, - size_t *r_nbytes) -{ - enum decoder_states ds = state->idx; - unsigned char val = state->radbuf[0]; - int pos = state->quad_count; - char *d, *s; - - if (state->stop_seen) - { - *r_nbytes = 0; - return gpg_error (GPG_ERR_EOF); - } - - for (s=d=buffer; length && !state->stop_seen; length--, s++) - { - switch (ds) - { - case s_idle: - if (*s == '\n') - { - ds = s_lfseen; - pos = 0; - } - break; - case s_init: - ds = s_lfseen; - case s_lfseen: - if (*s != "-----BEGIN "[pos]) - ds = s_idle; - else if (pos == 10) - ds = s_begin; - else - pos++; - break; - case s_begin: - if (*s == '\n') - ds = s_b64_0; - break; - case s_b64_0: - case s_b64_1: - case s_b64_2: - case s_b64_3: - { - int c; - - if (*s == '-' && state->title) - { - /* Not a valid Base64 character: assume end - header. */ - ds = s_waitend; - } - else if (*s == '=') - { - /* Pad character: stop */ - if (ds == s_b64_1) - *d++ = val; - ds = state->title? s_waitendtitle : s_waitend; - } - else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t') - ; /* Skip white spaces. */ - else if ( (*s & 0x80) - || (c = asctobin[*(unsigned char *)s]) == 255) - { - /* Skip invalid encodings. */ - state->invalid_encoding = 1; - } - else if (ds == s_b64_0) - { - val = c << 2; - ds = s_b64_1; - } - else if (ds == s_b64_1) - { - val |= (c>>4)&3; - *d++ = val; - val = (c<<4)&0xf0; - ds = s_b64_2; - } - else if (ds == s_b64_2) - { - val |= (c>>2)&15; - *d++ = val; - val = (c<<6)&0xc0; - ds = s_b64_3; - } - else - { - val |= c&0x3f; - *d++ = val; - ds = s_b64_0; - } - } - break; - case s_waitendtitle: - if (*s == '-') - ds = s_waitend; - break; - case s_waitend: - if ( *s == '\n') - state->stop_seen = 1; - break; - default: - BUG(); - } - } - - - state->idx = ds; - state->radbuf[0] = val; - state->quad_count = pos; - *r_nbytes = (d -(char*) buffer); - return 0; -} - - -/* This function needs to be called before releasing the decoder - state. It may return an error code in case an encoding error has - been found during decoding. */ -gpg_error_t -b64dec_finish (struct b64state *state) -{ - xfree (state->title); - state->title = NULL; - return state->invalid_encoding? gpg_error(GPG_ERR_BAD_DATA): 0; -} - diff --git a/dirmngr/b64enc.c b/dirmngr/b64enc.c deleted file mode 100644 index 4429a8e75..000000000 --- a/dirmngr/b64enc.c +++ /dev/null @@ -1,213 +0,0 @@ -/* b64enc.c - Simple Base64 encoder. - * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <assert.h> - -#include "i18n.h" -#include "util.h" - -#define B64ENC_DID_HEADER 1 -#define B64ENC_DID_TRAILER 2 -#define B64ENC_NO_LINEFEEDS 16 - - -/* The base-64 character list */ -static unsigned char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - -/* Prepare for base-64 writing to the stream FP. If TITLE is not NULL - and not an empty string, this string will be used as the title for - the armor lines, with TITLE being an empty string, we don't write - the header lines and furthermore even don't write any linefeeds. - With TITLE beeing NULL, we merely don't write header but make sure - that lines are not too long. Note, that we don't write any output - unless at least one byte get written using b64enc_write. */ -gpg_error_t -b64enc_start (struct b64state *state, FILE *fp, const char *title) -{ - memset (state, 0, sizeof *state); - state->fp = fp; - if (title && !*title) - state->flags |= B64ENC_NO_LINEFEEDS; - else if (title) - { - state->title = strdup (title); - if (!state->title) - return gpg_error_from_errno (errno); - } - return 0; -} - - -/* Write NBYTES from BUFFER to the Base 64 stream identified by - STATE. With BUFFER and NBYTES being 0, merely do a fflush on the - stream. */ -gpg_error_t -b64enc_write (struct b64state *state, const void *buffer, size_t nbytes) -{ - unsigned char radbuf[4]; - int idx, quad_count; - const unsigned char *p; - FILE *fp = state->fp; - - - if (!nbytes) - { - if (buffer && fflush (fp)) - goto write_error; - return 0; - } - - if (!(state->flags & B64ENC_DID_HEADER)) - { - if (state->title) - { - if ( fputs ("-----BEGIN ", fp) == EOF - || fputs (state->title, fp) == EOF - || fputs ("-----\n", fp) == EOF) - goto write_error; - } - state->flags |= B64ENC_DID_HEADER; - } - - idx = state->idx; - quad_count = state->quad_count; - assert (idx < 4); - memcpy (radbuf, state->radbuf, idx); - - for (p=buffer; nbytes; p++, nbytes--) - { - radbuf[idx++] = *p; - if (idx > 2) - { - char tmp[4]; - - tmp[0] = bintoasc[(*radbuf >> 2) & 077]; - tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; - tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; - tmp[3] = bintoasc[radbuf[2]&077]; - for (idx=0; idx < 4; idx++) - putc (tmp[idx], fp); - idx = 0; - if (ferror (fp)) - goto write_error; - if (++quad_count >= (64/4)) - { - quad_count = 0; - if (!(state->flags & B64ENC_NO_LINEFEEDS) - && fputs ("\n", fp) == EOF) - goto write_error; - } - } - } - memcpy (state->radbuf, radbuf, idx); - state->idx = idx; - state->quad_count = quad_count; - return 0; - - write_error: - return gpg_error_from_errno (errno); -} - -gpg_error_t -b64enc_finish (struct b64state *state) -{ - gpg_error_t err = 0; - unsigned char radbuf[4]; - int idx, quad_count; - FILE *fp; - - if (!(state->flags & B64ENC_DID_HEADER)) - goto cleanup; - - /* Flush the base64 encoding */ - fp = state->fp; - idx = state->idx; - quad_count = state->quad_count; - assert (idx < 4); - memcpy (radbuf, state->radbuf, idx); - - if (idx) - { - char tmp[4]; - - tmp[0] = bintoasc[(*radbuf>>2)&077]; - if (idx == 1) - { - tmp[1] = bintoasc[((*radbuf << 4) & 060) & 077]; - tmp[2] = '='; - tmp[3] = '='; - } - else - { - tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077]; - tmp[2] = bintoasc[((radbuf[1] << 2) & 074) & 077]; - tmp[3] = '='; - } - for (idx=0; idx < 4; idx++) - putc (tmp[idx], fp); - idx = 0; - if (ferror (fp)) - goto write_error; - - if (++quad_count >= (64/4)) - { - quad_count = 0; - if (!(state->flags & B64ENC_NO_LINEFEEDS) - && fputs ("\n", fp) == EOF) - goto write_error; - } - } - - /* Finish the last line and write the trailer. */ - if (quad_count - && !(state->flags & B64ENC_NO_LINEFEEDS) - && fputs ("\n", fp) == EOF) - goto write_error; - - if (state->title) - { - if ( fputs ("-----END ", fp) == EOF - || fputs (state->title, fp) == EOF - || fputs ("-----\n", fp) == EOF) - goto write_error; - } - - goto cleanup; - - write_error: - err = gpg_error_from_errno (errno); - - cleanup: - if (state->title) - { - free (state->title); - state->title = NULL; - } - state->fp = NULL; - return err; -} - diff --git a/dirmngr/cdblib.c b/dirmngr/cdblib.c index de60fe926..16d53aed8 100644 --- a/dirmngr/cdblib.c +++ b/dirmngr/cdblib.c @@ -73,6 +73,8 @@ # endif #endif #include <sys/stat.h> + +#include "dirmngr-err.h" #include "cdb.h" #ifndef EPROTO @@ -123,13 +125,17 @@ cdb_init(struct cdb *cdbp, int fd) return -1; /* trivial sanity check: at least toc should be here */ if (st.st_size < 2048) { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } fsize = (unsigned)(st.st_size & 0xffffffffu); /* memory-map file */ #ifdef _WIN32 +# ifdef __MINGW32CE__ + hFile = fd; +# else hFile = (HANDLE) _get_osfhandle(fd); +#endif if (hFile == (HANDLE) -1) return -1; hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); @@ -177,7 +183,11 @@ cdb_free(struct cdb *cdbp) HANDLE hFile, hMapping; #endif #ifdef _WIN32 +#ifdef __MINGW32CE__ + hFile = cdbp->cdb_fd; +#else hFile = (HANDLE) _get_osfhandle(cdbp->cdb_fd); +#endif hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); UnmapViewOfFile((void*) cdbp->cdb_mem); CloseHandle(hMapping); @@ -199,7 +209,7 @@ int cdb_read(const struct cdb *cdbp, void *buf, unsigned len, cdbi_t pos) { if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } memcpy(buf, cdbp->cdb_mem + pos, len); @@ -243,7 +253,7 @@ cdb_find(struct cdb *cdbp, const void *key, cdbi_t klen) || pos > cdbp->cdb_fsize /* htab start within file ? */ || httodo > cdbp->cdb_fsize - pos) /* entrie htab within file ? */ { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } @@ -258,19 +268,19 @@ cdb_find(struct cdb *cdbp, const void *key, cdbi_t klen) return 0; if (cdb_unpack(htp) == hval) { if (pos > cdbp->cdb_fsize - 8) { /* key+val lengths */ - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } if (cdb_unpack(cdbp->cdb_mem + pos) == klen) { if (cdbp->cdb_fsize - klen < pos + 8) { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } if (memcmp(key, cdbp->cdb_mem + pos + 8, klen) == 0) { n = cdb_unpack(cdbp->cdb_mem + pos + 4); pos += 8 + klen; if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos) { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } cdbp->cdb_vpos = pos; @@ -331,7 +341,7 @@ cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp, || pos > cdbp->cdb_fsize || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos) { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } @@ -368,12 +378,12 @@ cdb_findnext(struct cdb_find *cdbfp) cdbfp->cdb_httodo -= 8; if (n) { if (pos > cdbp->cdb_fsize - 8) { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } if (cdb_unpack(cdbp->cdb_mem + pos) == cdbfp->cdb_klen) { if (cdbp->cdb_fsize - cdbfp->cdb_klen < pos + 8) { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } if (memcmp(cdbfp->cdb_key, @@ -381,7 +391,7 @@ cdb_findnext(struct cdb_find *cdbfp) n = cdb_unpack(cdbp->cdb_mem + pos + 4); pos += 8 + cdbfp->cdb_klen; if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos) { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } cdbp->cdb_vpos = pos; @@ -410,7 +420,7 @@ cdb_findnext(struct cdb_find *cdbfp) || pos > cdbp->cdb_fsize || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos) { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } @@ -425,7 +435,7 @@ cdb_findnext(struct cdb_find *cdbfp) while (!pos); if (pos > cdbp->cdb_fsize - 8) { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } @@ -436,7 +446,7 @@ cdb_findnext(struct cdb_find *cdbfp) n = 8 + cdbp->cdb_klen + cdbp->cdb_vlen; if ( pos > cdbp->cdb_fsize || pos > cdbp->cdb_fsize - n) { - errno = EPROTO; + gpg_err_set_errno (EPROTO); return -1; } return 1; /* Found. */ @@ -454,7 +464,7 @@ cdb_bread(int fd, void *buf, int len) while(l < 0 && errno == EINTR); if (l <= 0) { if (!l) - errno = EIO; + gpg_err_set_errno (EIO); return -1; } buf = (char*)buf + l; @@ -555,7 +565,7 @@ cdb_make_add(struct cdb_make *cdbmp, struct cdb_rl *rl; if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) || vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) { - errno = ENOMEM; + gpg_err_set_errno (ENOMEM); return -1; } hval = cdb_hash(key, klen); @@ -563,7 +573,7 @@ cdb_make_add(struct cdb_make *cdbmp, if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) { rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl)); if (!rl) { - errno = ENOMEM; + gpg_err_set_errno (ENOMEM); return -1; } rl->cnt = 0; @@ -603,7 +613,7 @@ cdb_make_put(struct cdb_make *cdbmp, return -1; if (c) { if (flags == CDB_PUT_INSERT) { - errno = EEXIST; + gpg_err_set_errno (EEXIST); return 1; } else if (flags == CDB_PUT_REPLACE) { @@ -621,7 +631,7 @@ cdb_make_put(struct cdb_make *cdbmp, if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) { rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl)); if (!rl) { - errno = ENOMEM; + gpg_err_set_errno (ENOMEM); return -1; } rl->cnt = 0; @@ -633,13 +643,13 @@ cdb_make_put(struct cdb_make *cdbmp, break; default: - errno = EINVAL; + gpg_err_set_errno (EINVAL); return -1; } if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) || vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) { - errno = ENOMEM; + gpg_err_set_errno (ENOMEM); return -1; } rl->rec[c].hval = hval; @@ -812,7 +822,7 @@ cdb_make_finish_internal(struct cdb_make *cdbmp) unsigned t, i; if (((0xffffffff - cdbmp->cdb_dpos) >> 3) < cdbmp->cdb_rcnt) { - errno = ENOMEM; + gpg_err_set_errno (ENOMEM); return -1; } @@ -837,7 +847,7 @@ cdb_make_finish_internal(struct cdb_make *cdbmp) /* allocate memory to hold max htable */ htab = (struct cdb_rec*)malloc((hsize + 2) * sizeof(struct cdb_rec)); if (!htab) { - errno = ENOENT; + gpg_err_set_errno (ENOENT); return -1; } p = (unsigned char *)htab; diff --git a/dirmngr/certcache.c b/dirmngr/certcache.c index c40bb17d0..46d2ac365 100644 --- a/dirmngr/certcache.c +++ b/dirmngr/certcache.c @@ -328,7 +328,7 @@ load_certs_from_dir (const char *dirname, int are_trusted) struct dirent *ep; char *p; size_t n; - FILE *fp; + estream_t fp; ksba_reader_t reader; ksba_cert_t cert; char *fname = NULL; @@ -353,7 +353,7 @@ load_certs_from_dir (const char *dirname, int are_trusted) xfree (fname); fname = make_filename (dirname, p, NULL); - fp = fopen (fname, "rb"); + fp = es_fopen (fname, "rb"); if (!fp) { log_error (_("can't open `%s': %s\n"), @@ -367,7 +367,7 @@ load_certs_from_dir (const char *dirname, int are_trusted) { log_error (_("can't setup KSBA reader: %s\n"), gpg_strerror (err)); ksba_reader_release (reader); - fclose (fp); + es_fclose (fp); continue; } @@ -375,7 +375,7 @@ load_certs_from_dir (const char *dirname, int are_trusted) if (!err) err = ksba_cert_read_der (cert, reader); ksba_reader_release (reader); - fclose (fp); + es_fclose (fp); if (err) { log_error (_("can't parse certificate `%s': %s\n"), diff --git a/dirmngr/crlcache.c b/dirmngr/crlcache.c index 9ec5414fa..aeb6304b0 100644 --- a/dirmngr/crlcache.c +++ b/dirmngr/crlcache.c @@ -218,7 +218,7 @@ create_directory_if_needed (const char *name) log_error (_("error creating directory `%s': %s\n"), fname, strerror (errno)); xfree (fname); - errno = save_errno; + gpg_err_set_errno (save_errno); return -1; } } @@ -298,7 +298,7 @@ cleanup_cache_dir (int force) removed, the function will read the last line of a file, even if that is not terminated by a LF. */ static char * -next_line_from_file (FILE *fp, gpg_error_t *r_err) +next_line_from_file (estream_t fp, gpg_error_t *r_err) { char buf[300]; char *largebuf = NULL; @@ -311,7 +311,7 @@ next_line_from_file (FILE *fp, gpg_error_t *r_err) *r_err = 0; p = buf; buflen = sizeof buf - 1; - while ((c=getc (fp)) != EOF && c != '\n') + while ((c=es_getc (fp)) != EOF && c != '\n') { if (len >= buflen) { @@ -401,12 +401,12 @@ release_cache (crl_cache_t cache) /* Open the dir file FNAME or create a new one if it does not yet exist. */ -static FILE * +static estream_t open_dir_file (const char *fname) { - FILE *fp; + estream_t fp; - fp = fopen (fname, "r"); + fp = es_fopen (fname, "r"); if (!fp) { log_error (_("failed to open cache dir file `%s': %s\n"), @@ -416,22 +416,22 @@ open_dir_file (const char *fname) if (create_directory_if_needed (NULL) || create_directory_if_needed (DBDIR_D)) return NULL; - fp = fopen (fname, "w"); + fp = es_fopen (fname, "w"); if (!fp) { log_error (_("error creating new cache dir file `%s': %s\n"), fname, strerror (errno)); return NULL; } - fprintf (fp, "v:%d:\n", DBDIRVERSION); - if (ferror (fp)) + es_fprintf (fp, "v:%d:\n", DBDIRVERSION); + if (es_ferror (fp)) { log_error (_("error writing new cache dir file `%s': %s\n"), fname, strerror (errno)); - fclose (fp); + es_fclose (fp); return NULL; } - if (fclose (fp)) + if (es_fclose (fp)) { log_error (_("error closing new cache dir file `%s': %s\n"), fname, strerror (errno)); @@ -440,7 +440,7 @@ open_dir_file (const char *fname) log_info (_("new cache dir file `%s' created\n"), fname); - fp = fopen (fname, "r"); + fp = es_fopen (fname, "r"); if (!fp) { log_error (_("failed to re-open cache dir file `%s': %s\n"), @@ -454,13 +454,13 @@ open_dir_file (const char *fname) /* Helper for open_dir. */ static gpg_error_t -check_dir_version (FILE **fpadr, const char *fname, +check_dir_version (estream_t *fpadr, const char *fname, unsigned int *lineno, int cleanup_on_mismatch) { char *line; gpg_error_t lineerr = 0; - FILE *fp = *fpadr; + estream_t fp = *fpadr; int created = 0; retry: @@ -485,7 +485,7 @@ check_dir_version (FILE **fpadr, const char *fname, if (!created && cleanup_on_mismatch) { log_error (_("old version of cache directory - cleaning up\n")); - fclose (fp); + es_fclose (fp); *fpadr = NULL; if (!cleanup_cache_dir (1)) { @@ -521,7 +521,7 @@ open_dir (crl_cache_t *r_cache) char *fname; char *line = NULL; gpg_error_t lineerr = 0; - FILE *fp; + estream_t fp; crl_cache_entry_t entry, *entrytail; unsigned int lineno; gpg_error_t err = 0; @@ -649,7 +649,7 @@ open_dir (crl_cache_t *r_cache) log_error (_("error reading `%s': %s\n"), fname, gpg_strerror (err)); goto leave; } - if (ferror (fp)) + if (es_ferror (fp)) { log_error (_("error reading `%s': %s\n"), fname, strerror (errno)); err = gpg_error (GPG_ERR_CONFIGURATION); @@ -695,8 +695,7 @@ open_dir (crl_cache_t *r_cache) leave: - if (fp) - fclose (fp); + es_fclose (fp); xfree (line); xfree (fname); if (err) @@ -709,54 +708,54 @@ open_dir (crl_cache_t *r_cache) } static void -write_percented_string (const char *s, FILE *fp) +write_percented_string (const char *s, estream_t fp) { for (; *s; s++) if (*s == ':') - fputs ("%3A", fp); + es_fputs ("%3A", fp); else if (*s == '\n') - fputs ("%0A", fp); + es_fputs ("%0A", fp); else if (*s == '\r') - fputs ("%0D", fp); + es_fputs ("%0D", fp); else - putc (*s, fp); + es_putc (*s, fp); } static void -write_dir_line_crl (FILE *fp, crl_cache_entry_t e) +write_dir_line_crl (estream_t fp, crl_cache_entry_t e) { if (e->invalid) - fprintf (fp, "i%d", e->invalid); + es_fprintf (fp, "i%d", e->invalid); else if (e->user_trust_req) - putc ('u', fp); + es_putc ('u', fp); else - putc ('c', fp); - putc (':', fp); - fputs (e->issuer_hash, fp); - putc (':', fp); + es_putc ('c', fp); + es_putc (':', fp); + es_fputs (e->issuer_hash, fp); + es_putc (':', fp); write_percented_string (e->issuer, fp); - putc (':', fp); + es_putc (':', fp); write_percented_string (e->url, fp); - putc (':', fp); - fwrite (e->this_update, 15, 1, fp); - putc (':', fp); - fwrite (e->next_update, 15, 1, fp); - putc (':', fp); - fputs (e->dbfile_hash, fp); - putc (':', fp); + es_putc (':', fp); + es_fwrite (e->this_update, 15, 1, fp); + es_putc (':', fp); + es_fwrite (e->next_update, 15, 1, fp); + es_putc (':', fp); + es_fputs (e->dbfile_hash, fp); + es_putc (':', fp); if (e->crl_number) - fputs (e->crl_number, fp); - putc (':', fp); + es_fputs (e->crl_number, fp); + es_putc (':', fp); if (e->authority_issuer) write_percented_string (e->authority_issuer, fp); - putc (':', fp); + es_putc (':', fp); if (e->authority_serialno) - fputs (e->authority_serialno, fp); - putc (':', fp); + es_fputs (e->authority_serialno, fp); + es_putc (':', fp); if (e->check_trust_anchor && e->user_trust_req) - fputs (e->check_trust_anchor, fp); - putc ('\n', fp); + es_fputs (e->check_trust_anchor, fp); + es_putc ('\n', fp); } @@ -768,7 +767,8 @@ update_dir (crl_cache_t cache) char *tmpfname = NULL; char *line = NULL; gpg_error_t lineerr = 0; - FILE *fp, *fpout = NULL; + estream_t fp; + estream_t fpout = NULL; crl_cache_entry_t e; unsigned int lineno; gpg_error_t err = 0; @@ -781,7 +781,7 @@ update_dir (crl_cache_t cache) e->mark = 1; lineno = 0; - fp = fopen (fname, "r"); + fp = es_fopen (fname, "r"); if (!fp) { err = gpg_error_from_errno (errno); @@ -792,7 +792,7 @@ update_dir (crl_cache_t cache) err = check_dir_version (&fp, fname, &lineno, 0); if (err) goto leave; - rewind (fp); + es_rewind (fp); lineno = 0; /* Create a temporary DIR file. */ @@ -827,7 +827,7 @@ update_dir (crl_cache_t cache) tmpfname = make_filename (opt.homedir_cache, DBDIR_D, tmpbuf, NULL); xfree (tmpbuf); } - fpout = fopen (tmpfname, "w"); + fpout = es_fopen (tmpfname, "w"); if (!fpout) { err = gpg_error_from_errno (errno); @@ -868,30 +868,30 @@ update_dir (crl_cache_t cache) { /* We ignore entries we don't have in our cache because they may have been added in the meantime by other instances of dirmngr. */ - fprintf (fpout, "# Next line added by " - "another process; our pid is %lu\n", - (unsigned long)getpid ()); - fputs (line, fpout); - putc ('\n', fpout); + es_fprintf (fpout, "# Next line added by " + "another process; our pid is %lu\n", + (unsigned long)getpid ()); + es_fputs (line, fpout); + es_putc ('\n', fpout); } } else { - fputs ("# Invalid line detected: ", fpout); - fputs (line, fpout); - putc ('\n', fpout); + es_fputs ("# Invalid line detected: ", fpout); + es_fputs (line, fpout); + es_putc ('\n', fpout); } } else { /* Write out all non CRL lines as they are. */ - fputs (line, fpout); - putc ('\n', fpout); + es_fputs (line, fpout); + es_putc ('\n', fpout); } xfree (line); } - if (!ferror (fp) && !ferror (fpout) && !lineerr) + if (!es_ferror (fp) && !ferror (es_fpout) && !lineerr) { /* Write out the remaining entries. */ for (e= cache->entries; e; e = e->next) @@ -908,12 +908,12 @@ update_dir (crl_cache_t cache) log_error (_("error reading `%s': %s\n"), fname, gpg_strerror (err)); goto leave; } - if (ferror (fp)) + if (es_ferror (fp)) { err = gpg_error_from_errno (errno); log_error (_("error reading `%s': %s\n"), fname, strerror (errno)); } - if (ferror (fpout)) + if (es_ferror (fpout)) { err = gpg_error_from_errno (errno); log_error (_("error writing `%s': %s\n"), tmpfname, strerror (errno)); @@ -922,9 +922,9 @@ update_dir (crl_cache_t cache) goto leave; /* Rename the files. */ - fclose (fp); + es_fclose (fp); fp = NULL; - if (fclose (fpout)) + if (es_fclose (fpout)) { err = gpg_error_from_errno (errno); log_error (_("error closing `%s': %s\n"), tmpfname, strerror (errno)); @@ -947,14 +947,13 @@ update_dir (crl_cache_t cache) leave: /* Fixme: Relinquish update lock. */ xfree (line); - if (fp) - fclose (fp); + es_fclose (fp); xfree (fname); if (fpout) { - fclose (fpout); + es_fclose (fpout); if (err && tmpfname) - remove (tmpfname); + gnupg_remove (tmpfname); } xfree (tmpfname); return err; @@ -984,14 +983,14 @@ make_db_file_name (const char *issuer_hash) static int hash_dbfile (const char *fname, unsigned char *md5buffer) { - FILE *fp; + estream_t fp; char *buffer; size_t n; gcry_md_hd_t md5; gpg_err_code_t err; buffer = xtrymalloc (65536); - fp = buffer? fopen (fname, "rb") : NULL; + fp = buffer? es_fopen (fname, "rb") : NULL; if (!fp) { log_error (_("can't hash `%s': %s\n"), fname, strerror (errno)); @@ -1005,7 +1004,7 @@ hash_dbfile (const char *fname, unsigned char *md5buffer) log_error (_("error setting up MD5 hash context: %s\n"), gpg_strerror (err)); xfree (buffer); - fclose (fp); + es_fclose (fp); return -1; } @@ -1015,12 +1014,12 @@ hash_dbfile (const char *fname, unsigned char *md5buffer) for (;;) { - n = fread (buffer, 1, 65536, fp); - if (n < 65536 && ferror (fp)) + n = es_fread (buffer, 1, 65536, fp); + if (n < 65536 && es_ferror (fp)) { log_error (_("error hashing `%s': %s\n"), fname, strerror (errno)); xfree (buffer); - fclose (fp); + es_fclose (fp); gcry_md_close (md5); return -1; } @@ -1028,7 +1027,7 @@ hash_dbfile (const char *fname, unsigned char *md5buffer) break; gcry_md_write (md5, buffer, n); } - fclose (fp); + es_fclose (fp); xfree (buffer); gcry_md_final (md5); @@ -2017,7 +2016,7 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader) *p = '.'; fname = make_filename (opt.homedir_cache, DBDIR_D, tmpfname, NULL); xfree (tmpfname); - if (!remove (fname)) + if (!gnupg_remove (fname)) log_info (_("removed stale temporary cache file `%s'\n"), fname); else if (errno != ENOENT) { @@ -2198,7 +2197,7 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader) close (fd_cdb); if (fname) { - remove (fname); + gnupg_remove (fname); xfree (fname); } xfree (newfname); @@ -2214,7 +2213,7 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader) /* Print one cached entry E in a human readable format to stream FP. Return 0 on success. */ static gpg_error_t -list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, FILE *fp) +list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, estream_t fp) { struct cdb_find cdbfp; struct cdb *cdb; @@ -2222,44 +2221,46 @@ list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, FILE *fp) int warn = 0; const unsigned char *s; - fputs ("--------------------------------------------------------\n", fp ); - fprintf (fp, _("Begin CRL dump (retrieved via %s)\n"), e->url ); - fprintf (fp, " Issuer:\t%s\n", e->issuer ); - fprintf (fp, " Issuer Hash:\t%s\n", e->issuer_hash ); - fprintf (fp, " This Update:\t%s\n", e->this_update ); - fprintf (fp, " Next Update:\t%s\n", e->next_update ); - fprintf (fp, " CRL Number :\t%s\n", e->crl_number? e->crl_number: "none"); - fprintf (fp, " AuthKeyId :\t%s\n", - e->authority_serialno? e->authority_serialno:"none"); + es_fputs ("--------------------------------------------------------\n", fp ); + es_fprintf (fp, _("Begin CRL dump (retrieved via %s)\n"), e->url ); + es_fprintf (fp, " Issuer:\t%s\n", e->issuer ); + es_fprintf (fp, " Issuer Hash:\t%s\n", e->issuer_hash ); + es_fprintf (fp, " This Update:\t%s\n", e->this_update ); + es_fprintf (fp, " Next Update:\t%s\n", e->next_update ); + es_fprintf (fp, " CRL Number :\t%s\n", e->crl_number? e->crl_number: "none"); + es_fprintf (fp, " AuthKeyId :\t%s\n", + e->authority_serialno? e->authority_serialno:"none"); if (e->authority_serialno && e->authority_issuer) { - fputs (" \t", fp); + es_fputs (" \t", fp); for (s=e->authority_issuer; *s; s++) if (*s == '\x01') - fputs ("\n \t", fp); + es_fputs ("\n \t", fp); else - putc (*s, fp); - putc ('\n', fp); + es_putc (*s, fp); + es_putc ('\n', fp); } - fprintf (fp, " Trust Check:\t%s\n", - !e->user_trust_req? "[system]" : - e->check_trust_anchor? e->check_trust_anchor:"[missing]"); + es_fprintf (fp, " Trust Check:\t%s\n", + !e->user_trust_req? "[system]" : + e->check_trust_anchor? e->check_trust_anchor:"[missing]"); if ((e->invalid & 1)) - fprintf (fp, _(" ERROR: The CRL will not be used because it was still too old after an update!\n")); + es_fprintf (fp, _(" ERROR: The CRL will not be used " + "because it was still too old after an update!\n")); if ((e->invalid & 2)) - fprintf (fp, _(" ERROR: The CRL will not be used due to an unknown critical extension!\n")); + es_fprintf (fp, _(" ERROR: The CRL will not be used " + "due to an unknown critical extension!\n")); if ((e->invalid & ~3)) - fprintf (fp, _(" ERROR: The CRL will not be used\n")); + es_fprintf (fp, _(" ERROR: The CRL will not be used\n")); cdb = lock_db_file (cache, e); if (!cdb) return gpg_error (GPG_ERR_GENERAL); if (!e->dbfile_checked) - fprintf (fp, _(" ERROR: This cached CRL may has been tampered with!\n")); + es_fprintf (fp, _(" ERROR: This cached CRL may has been tampered with!\n")); - putc ('\n', fp); + es_putc ('\n', fp); rc = cdb_findinit (&cdbfp, cdb, NULL, 0); while (!rc && (rc=cdb_findnext (&cdbfp)) > 0 ) @@ -2299,36 +2300,36 @@ list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, FILE *fp) } reason = *record; - fputs (" ", fp); + es_fputs (" ", fp); for (i = 0; i < n; i++) - fprintf (fp, "%02X", keyrecord[i]); - fputs (":\t reasons( ", fp); + es_fprintf (fp, "%02X", keyrecord[i]); + es_fputs (":\t reasons( ", fp); if (reason & KSBA_CRLREASON_UNSPECIFIED) - fputs( "unspecified ", fp ), any = 1; + es_fputs( "unspecified ", fp ), any = 1; if (reason & KSBA_CRLREASON_KEY_COMPROMISE ) - fputs( "key_compromise ", fp ), any = 1; + es_fputs( "key_compromise ", fp ), any = 1; if (reason & KSBA_CRLREASON_CA_COMPROMISE ) - fputs( "ca_compromise ", fp ), any = 1; + es_fputs( "ca_compromise ", fp ), any = 1; if (reason & KSBA_CRLREASON_AFFILIATION_CHANGED ) - fputs( "affiliation_changed ", fp ), any = 1; + es_fputs( "affiliation_changed ", fp ), any = 1; if (reason & KSBA_CRLREASON_SUPERSEDED ) - fputs( "superseeded", fp ), any = 1; + es_fputs( "superseeded", fp ), any = 1; if (reason & KSBA_CRLREASON_CESSATION_OF_OPERATION ) - fputs( "cessation_of_operation", fp ), any = 1; + es_fputs( "cessation_of_operation", fp ), any = 1; if (reason & KSBA_CRLREASON_CERTIFICATE_HOLD ) - fputs( "certificate_hold", fp ), any = 1; + es_fputs( "certificate_hold", fp ), any = 1; if (reason && !any) - fputs( "other", fp ); + es_fputs( "other", fp ); - fprintf (fp, ") rdate: %.15s\n", record+1); + es_fprintf (fp, ") rdate: %.15s\n", record+1); } if (rc) log_error (_("error reading cache entry from db: %s\n"), strerror (rc)); unlock_db_file (cache, e); - fprintf (fp, _("End CRL dump\n") ); - putc ('\n', fp); + es_fprintf (fp, _("End CRL dump\n") ); + es_putc ('\n', fp); return (rc||warn)? gpg_error (GPG_ERR_GENERAL) : 0; } @@ -2337,7 +2338,7 @@ list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, FILE *fp) /* Print the contents of the CRL CACHE in a human readable format to stream FP. */ gpg_error_t -crl_cache_list (FILE *fp) +crl_cache_list (estream_t fp) { crl_cache_t cache = get_current_cache (); crl_cache_entry_t entry; @@ -2357,10 +2358,10 @@ gpg_error_t crl_cache_load (ctrl_t ctrl, const char *filename) { gpg_error_t err; - FILE *fp; + estream_t fp; ksba_reader_t reader; - fp = fopen (filename, "r"); + fp = es_fopen (filename, "r"); if (!fp) { err = gpg_error_from_errno (errno); @@ -2380,7 +2381,7 @@ crl_cache_load (ctrl_t ctrl, const char *filename) } err = crl_cache_insert (ctrl, filename, reader); ksba_reader_release (reader); - fclose (fp); + es_fclose (fp); return err; } diff --git a/dirmngr/crlcache.h b/dirmngr/crlcache.h index b9e487436..c2995129c 100644 --- a/dirmngr/crlcache.h +++ b/dirmngr/crlcache.h @@ -60,7 +60,7 @@ gpg_error_t crl_cache_cert_isvalid (ctrl_t ctrl, ksba_cert_t cert, gpg_error_t crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader); -gpg_error_t crl_cache_list (FILE* fp); +gpg_error_t crl_cache_list (estream_t fp); gpg_error_t crl_cache_load (ctrl_t ctrl, const char *filename); diff --git a/dirmngr/crlfetch.c b/dirmngr/crlfetch.c index ca6c77a84..e89931e89 100644 --- a/dirmngr/crlfetch.c +++ b/dirmngr/crlfetch.c @@ -193,9 +193,8 @@ crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader) else err = http_open_document (&hd, url, NULL, (opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0) - |HTTP_FLAG_NEED_HEADER |(DBG_LOOKUP? HTTP_FLAG_LOG_RESP:0), - opt.http_proxy, NULL); + opt.http_proxy, NULL, NULL, NULL); switch ( err? 99999 : http_get_status_code (hd) ) { diff --git a/dirmngr/dirmngr-client.c b/dirmngr/dirmngr-client.c index 00b12b712..5aba0c80a 100644 --- a/dirmngr/dirmngr-client.c +++ b/dirmngr/dirmngr-client.c @@ -485,7 +485,7 @@ start_dirmngr (int only_daemon) i=0; if (log_get_fd () != -1) no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ()); - no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr)); + no_close_list[i++] = assuan_fd_from_posix_fd (es_fileno (es_stderr)); no_close_list[i] = -1; /* Connect to the agent and perform initial handshaking. */ diff --git a/dirmngr/dirmngr-err.h b/dirmngr/dirmngr-err.h new file mode 100644 index 000000000..17e825570 --- /dev/null +++ b/dirmngr/dirmngr-err.h @@ -0,0 +1,12 @@ +/* Definition of the gpg-error source. */ + +#ifndef DIRMNGR_ERR_H +#define DIRMNGR_ERR_H + +#ifdef GPG_ERR_SOURCE_DEFAULT +#error GPG_ERR_SOURCE_DEFAULT already defined +#endif +#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_DIRMNGR +#include <gpg-error.h> + +#endif /*DIRMNGR_ERR_H*/ diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index 12b74bd00..5a913905d 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -37,7 +37,9 @@ #endif #include <sys/stat.h> #include <unistd.h> -#include <signal.h> +#ifdef HAVE_SIGNAL_H +# include <signal.h> +#endif #include <pth.h> @@ -53,6 +55,16 @@ #include "ldapserver.h" #include "asshelp.h" +/* The plain Windows version uses the windows service system. For + example to start the service you may use "sc start dirmngr". + WindowsCE does not support this; the service system over there is + based on a single process with all services being DLLs - we can't + support this easily. */ +#if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM) +# define USE_W32_SERVICE 1 +#endif + + enum cmd_and_opt_values { aNull = 0, oCsh = 'c', @@ -119,7 +131,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_c (aServer, "server", N_("run in server mode (foreground)") ), ARGPARSE_c (aDaemon, "daemon", N_("run in daemon mode (background)") ), -#ifdef HAVE_W32_SYSTEM +#ifdef USE_W32_SERVICE ARGPARSE_c (aService, "service", N_("run as windows service (background)")), #endif ARGPARSE_c (aListCRLs, "list-crls", N_("list the contents of the CRL cache")), @@ -374,9 +386,9 @@ set_debug (void) static void wrong_args (const char *text) { - fputs (_("usage: dirmngr [options] "), stderr); - fputs (text, stderr); - putc ('\n', stderr); + es_fputs (_("usage: dirmngr [options] "), es_stderr); + es_fputs (text, es_stderr); + es_putc ('\n', es_stderr); dirmngr_exit (2); } @@ -514,7 +526,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) } -#ifdef HAVE_W32_SYSTEM +#ifdef USE_W32_SERVICE /* The global status of our service. */ SERVICE_STATUS_HANDLE service_handle; SERVICE_STATUS service_status; @@ -544,7 +556,7 @@ w32_service_control (DWORD control, DWORD event_type, LPVOID event_data, } return 0; } -#endif /*HAVE_W32_SYSTEM*/ +#endif /*USE_W32_SERVICE*/ #ifndef HAVE_W32_SYSTEM static int @@ -559,14 +571,14 @@ pid_suffix_callback (unsigned long *r_suffix) #endif /*!HAVE_W32_SYSTEM*/ -#ifdef HAVE_W32_SYSTEM -#define main real_main +#ifdef USE_W32_SERVICE +# define main real_main #endif int main (int argc, char **argv) { -#ifdef HAVE_W32_SYSTEM -#undef main +#ifdef USE_W32_SERVICE +# undef main #endif enum cmd_and_opt_values cmd = 0; ARGPARSE_ARGS pargs; @@ -589,7 +601,7 @@ main (int argc, char **argv) int homedir_seen = 0; struct assuan_malloc_hooks malloc_hooks; -#ifdef HAVE_W32_SYSTEM +#ifdef USE_W32_SERVICE /* The option will be set by main() below if we should run as a system daemon. */ if (opt.system_service) @@ -610,7 +622,7 @@ main (int argc, char **argv) service_status.dwWaitHint = 10000; /* 10 seconds timeout. */ SetServiceStatus (service_handle, &service_status); } -#endif /*HAVE_W32_SYSTEM*/ +#endif /*USE_W32_SERVICE*/ set_strusage (my_strusage); log_set_prefix ("dirmngr", 1|4); @@ -833,7 +845,7 @@ main (int argc, char **argv) } if (configfp) { - fclose( configfp ); + fclose (configfp); configfp = NULL; /* Keep a copy of the name so that it can be read on SIGHUP. */ opt.config_filename = configname; @@ -854,15 +866,22 @@ main (int argc, char **argv) if (greeting) { - fprintf (stderr, "%s %s; %s\n", - strusage(11), strusage(13), strusage(14) ); - fprintf (stderr, "%s\n", strusage(15) ); + es_fprintf (es_stderr, "%s %s; %s\n", + strusage(11), strusage(13), strusage(14) ); + es_fprintf (es_stderr, "%s\n", strusage(15) ); } #ifdef IS_DEVELOPMENT_VERSION log_info ("NOTE: this is a development version!\n"); #endif + if (!access ("/etc/dirmngr", F_OK) && !strncmp (opt.homedir, "/etc/", 5)) + log_info + ("NOTE: DirMngr is now a proper part of GnuPG. The configuration and" + " other directory names changed. Please check that no other version" + " of dirmngr is still installed. To disable this warning, remove the" + " directory `/etc/dirmngr'.\n"); + if (gnupg_faked_time_p ()) { gnupg_isotime_t tbuf; @@ -975,7 +994,7 @@ main (int argc, char **argv) rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len); if (rc == -1 && errno == EADDRINUSE) { - remove (socket_name); + gnupg_remove (socket_name); rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len); } if (rc != -1 @@ -1000,7 +1019,7 @@ main (int argc, char **argv) if (opt.verbose) log_info (_("listening on socket `%s'\n"), socket_name ); - fflush (NULL); + es_fflush (NULL); #ifdef HAVE_W32_SYSTEM pid = getpid (); @@ -1085,7 +1104,7 @@ main (int argc, char **argv) launch_reaper_thread (); cert_cache_init (); crl_cache_init (); -#ifdef HAVE_W32_SYSTEM +#ifdef USE_W32_SERVICE if (opt.system_service) { service_status.dwCurrentState = SERVICE_RUNNING; @@ -1095,7 +1114,7 @@ main (int argc, char **argv) handle_connections (fd); assuan_sock_close (fd); shutdown_reaper (); -#ifdef HAVE_W32_SYSTEM +#ifdef USE_W32_SERVICE if (opt.system_service) { service_status.dwCurrentState = SERVICE_STOPPED; @@ -1110,7 +1129,7 @@ main (int argc, char **argv) wrong_args ("--list-crls"); launch_reaper_thread (); crl_cache_init (); - crl_cache_list (stdout); + crl_cache_list (es_stdout); } else if (cmd == aLoadCRL) { @@ -1260,7 +1279,7 @@ main (int argc, char **argv) } -#ifdef HAVE_W32_SYSTEM +#ifdef USE_W32_SERVICE int main (int argc, char *argv[]) { @@ -1291,7 +1310,7 @@ main (int argc, char *argv[]) return 0; } } -#endif +#endif /*USE_W32_SERVICE*/ static void @@ -1307,7 +1326,7 @@ cleanup (void) { cleanup_socket = 0; if (socket_name && *socket_name) - remove (socket_name); + gnupg_remove (socket_name); } } @@ -1351,9 +1370,9 @@ parse_ldapserver_file (const char* filename) ldap_server_t server, serverstart, *serverend; int c; unsigned int lineno = 0; - FILE *fp; + estream_t fp; - fp = fopen (filename, "r"); + fp = es_fopen (filename, "r"); if (!fp) { log_error (_("error opening `%s': %s\n"), filename, strerror (errno)); @@ -1362,18 +1381,18 @@ parse_ldapserver_file (const char* filename) serverstart = NULL; serverend = &serverstart; - while (fgets (buffer, sizeof buffer, fp)) + while (es_fgets (buffer, sizeof buffer, fp)) { lineno++; if (!*buffer || buffer[strlen(buffer)-1] != '\n') { - if (*buffer && feof (fp)) + if (*buffer && es_feof (fp)) ; /* Last line not terminated - continue. */ else { log_error (_("%s:%u: line too long - skipped\n"), filename, lineno); - while ( (c=fgetc (fp)) != EOF && c != '\n') + while ( (c=es_fgetc (fp)) != EOF && c != '\n') ; /* Skip until end of line. */ continue; } @@ -1393,9 +1412,9 @@ parse_ldapserver_file (const char* filename) } } - if (ferror (fp)) + if (es_ferror (fp)) log_error (_("error reading `%s': %s\n"), filename, strerror (errno)); - fclose (fp); + es_fclose (fp); return serverstart; } @@ -1406,7 +1425,7 @@ parse_ocsp_signer (const char *string) { gpg_error_t err; char *fname; - FILE *fp; + estream_t fp; char line[256]; char *p; fingerprint_list_t list, *list_tail, item; @@ -1444,7 +1463,7 @@ parse_ocsp_signer (const char *string) fname = make_filename (opt.homedir, string, NULL); } - fp = fopen (fname, "r"); + fp = es_fopen (fname, "r"); if (!fp) { err = gpg_error_from_syserror (); @@ -1457,16 +1476,16 @@ parse_ocsp_signer (const char *string) list_tail = &list; for (;;) { - if (!fgets (line, DIM(line)-1, fp) ) + if (!es_fgets (line, DIM(line)-1, fp) ) { - if (!feof (fp)) + if (!es_feof (fp)) { err = gpg_error_from_syserror (); log_error (_("%s:%u: read error: %s\n"), fname, lnr, gpg_strerror (err)); errflag = 1; } - fclose (fp); + es_fclose (fp); if (errflag) { while (list) @@ -1484,7 +1503,7 @@ parse_ocsp_signer (const char *string) if (!*line || line[strlen(line)-1] != '\n') { /* Eat until end of line. */ - while ( (c=getc (fp)) != EOF && c != '\n') + while ( (c=es_getc (fp)) != EOF && c != '\n') ; err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG /* */: GPG_ERR_INCOMPLETE_LINE); diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h index e6fa0d318..67f2122d9 100644 --- a/dirmngr/dirmngr.h +++ b/dirmngr/dirmngr.h @@ -21,11 +21,7 @@ #ifndef DIRMNGR_H #define DIRMNGR_H -#ifdef GPG_ERR_SOURCE_DEFAULT -#error GPG_ERR_SOURCE_DEFAULT already defined -#endif -#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_DIRMNGR -#include <gpg-error.h> +#include "./dirmngr-err.h" #define map_assuan_err(a) \ map_assuan_err_with_source (GPG_ERR_SOURCE_DEFAULT, (a)) #include <errno.h> diff --git a/dirmngr/dirmngr_ldap.c b/dirmngr/dirmngr_ldap.c index f862081c1..fccbc58d1 100644 --- a/dirmngr/dirmngr_ldap.c +++ b/dirmngr/dirmngr_ldap.c @@ -25,7 +25,9 @@ #include <stddef.h> #include <stdarg.h> #include <string.h> -#include <signal.h> +#ifdef HAVE_SIGNAL_H +# include <signal.h> +#endif #include <errno.h> #include <assert.h> #include <sys/time.h> @@ -171,6 +173,7 @@ main (int argc, char **argv ) #ifdef HAVE_W32_SYSTEM /* Yeah, right. Sigh. */ +#error FIXME _setmode (_fileno (stdout), _O_BINARY); #endif @@ -313,7 +316,7 @@ print_ldap_entries (LDAP *ld, LDAPMessage *msg, char *want_attr) if (opt.multi) { /* Write item marker. */ - if (fwrite ("I\0\0\0\0", 5, 1, stdout) != 1) + if (es_fwrite ("I\0\0\0\0", 5, 1, es_stdout) != 1) { log_error (_("error writing to stdout: %s\n"), strerror (errno)); @@ -390,8 +393,8 @@ print_ldap_entries (LDAP *ld, LDAPMessage *msg, char *want_attr) tmp[2] = (n >> 16); tmp[3] = (n >> 8); tmp[4] = (n); - if (fwrite (tmp, 5, 1, stdout) != 1 - || fwrite (attr, n, 1, stdout) != 1) + if (es_fwrite (tmp, 5, 1, es_stdout) != 1 + || es_fwrite (attr, n, 1, es_stdout) != 1) { log_error (_("error writing to stdout: %s\n"), strerror (errno)); @@ -415,7 +418,7 @@ print_ldap_entries (LDAP *ld, LDAPMessage *msg, char *want_attr) tmp[3] = (n >> 8); tmp[4] = (n); - if (fwrite (tmp, 5, 1, stdout) != 1) + if (es_fwrite (tmp, 5, 1, es_stdout) != 1) { log_error (_("error writing to stdout: %s\n"), strerror (errno)); @@ -429,8 +432,9 @@ print_ldap_entries (LDAP *ld, LDAPMessage *msg, char *want_attr) /* Note: this does not work for STDOUT on a Windows console, where it fails with "Not enough space" for CRLs which are 52 KB or larger. */ - if (fwrite (values[0]->bv_val, values[0]->bv_len, - 1, stdout) != 1) +#warning still true - implement in estream + if (es_fwrite (values[0]->bv_val, values[0]->bv_len, + 1, es_stdout) != 1) { log_error (_("error writing to stdout: %s\n"), strerror (errno)); @@ -452,8 +456,8 @@ print_ldap_entries (LDAP *ld, LDAPMessage *msg, char *want_attr) if (cnt > MAX_CNT) cnt = MAX_CNT; - if (fwrite (((char *) values[0]->bv_val) + n, cnt, 1, - stdout) != 1) + if (es_fwrite (((char *) values[0]->bv_val) + n, cnt, 1, + es_stdout) != 1) { log_error (_("error writing to stdout: %s\n"), strerror (errno)); @@ -572,7 +576,7 @@ fetch_ldap (const char *url, const LDAPURLDesc *ludp) &opt.timeout, &msg); if (rc == LDAP_SIZELIMIT_EXCEEDED && opt.multi) { - if (fwrite ("E\0\0\0\x09truncated", 14, 1, stdout) != 1) + if (es_fwrite ("E\0\0\0\x09truncated", 14, 1, es_stdout) != 1) { log_error (_("error writing to stdout: %s\n"), strerror (errno)); diff --git a/dirmngr/http.c b/dirmngr/http.c deleted file mode 100644 index b65a92adc..000000000 --- a/dirmngr/http.c +++ /dev/null @@ -1,1863 +0,0 @@ -/* http.c - HTTP protocol handler - * Copyright (C) 1999, 2001, 2002, 2003, 2004, - * 2006, 2009 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ - -/* Simple HTTP client implementation. We try to keep the code as - self-contained as possible. There are some contraints however: - - - estream is required. We now require estream because it provides a - very useful and portable asprintf implementation and the fopencookie - function. - - stpcpy is required - - fixme: list other requirements. - - - - With HTTP_USE_GNUTLS support for https is provided (this also - requires estream). - - With HTTP_NO_WSASTARTUP the socket initialization is not done - under Windows. This is useful if the socket layer has already - been initialized elsewhere. This also avoids the installation of - an exit handler to cleanup the socket layer. -*/ - -#warning Duplicated code with common/http.c - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <unistd.h> - -#ifdef HAVE_W32_SYSTEM -# include <windows.h> -#else /*!HAVE_W32_SYSTEM*/ -# include <sys/types.h> -# include <sys/socket.h> -# include <sys/time.h> -# include <time.h> -# include <netinet/in.h> -# include <arpa/inet.h> -# include <netdb.h> -#endif /*!HAVE_W32_SYSTEM*/ - -#include <pth.h> - -#ifdef HTTP_USE_GNUTLS -# include <gnutls/gnutls.h> -/* For non-understandable reasons GNUTLS dropped the _t suffix from - all types. yes, ISO-C might be read as this but there are still - other name space conflicts and using _t is actually a Good - Thing. */ -typedef gnutls_session gnutls_session_t; -typedef gnutls_transport_ptr gnutls_transport_ptr_t; -#endif /*HTTP_USE_GNUTLS*/ - -#ifdef TEST -#undef USE_DNS_SRV -#endif - -#include "util.h" -#include "i18n.h" -#include "http.h" -#ifdef USE_DNS_SRV -#include "srv.h" -#else /*!USE_DNS_SRV*/ -/* If we are not compiling with SRV record support we provide stub - data structures. */ -#ifndef MAXDNAME -#define MAXDNAME 1025 -#endif -struct srventry -{ - unsigned short priority; - unsigned short weight; - unsigned short port; - int run_count; - char target[MAXDNAME]; -}; -#endif/*!USE_DNS_SRV*/ - - -#ifdef HAVE_W32_SYSTEM -#define sock_close(a) closesocket(a) -#else -#define sock_close(a) close(a) -#endif - -#ifndef EAGAIN -#define EAGAIN EWOULDBLOCK -#endif - -#define HTTP_PROXY_ENV "http_proxy" -#define MAX_LINELEN 20000 /* Max. length of a HTTP header line. */ -#define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz" \ - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ - "01234567890@" \ - "!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~" - -/* A long counter type. */ -#ifdef HAVE_STRTOULL -typedef unsigned long long longcounter_t; -#define counter_strtoul(a) strtoull ((a), NULL, 10) -#else -typedef unsigned long longcounter_t; -#define counter_strtoul(a) strtoul ((a), NULL, 10) -#endif - -#ifndef HTTP_USE_GNUTLS -typedef void * gnutls_session_t; -#endif - -static gpg_error_t do_parse_uri (parsed_uri_t uri, int only_local_part); -static int remove_escapes (char *string); -static int insert_escapes (char *buffer, const char *string, - const char *special); -static uri_tuple_t parse_tuple (char *string); -static gpg_error_t send_request (http_t hd, - const char *auth, const char *proxy); -static char *build_rel_path (parsed_uri_t uri); -static gpg_error_t parse_response (http_t hd); - -static int connect_server (const char *server, unsigned short port, - unsigned int flags, const char *srvtag); - -static ssize_t cookie_read (void *cookie, void *buffer, size_t size); -static ssize_t cookie_write (void *cookie, const void *buffer, size_t size); -static int cookie_close (void *cookie); - -static es_cookie_io_functions_t cookie_functions = - { - cookie_read, - cookie_write, - NULL, - cookie_close - }; - -struct cookie_s -{ - int fd; /* File descriptor or -1 if already closed. */ - gnutls_session_t tls_session; /* TLS session context or NULL if not used. */ - - /* The remaining content length and a flag telling whether to use - the content length. */ - longcounter_t content_length; - unsigned int content_length_valid:1; - - /* Flag to communicate with the close handler. */ - unsigned int keep_socket:1; -}; -typedef struct cookie_s *cookie_t; - - -#ifdef HTTP_USE_GNUTLS -static gpg_error_t (*tls_callback) (http_t, gnutls_session_t, int); -#endif /*HTTP_USE_GNUTLS*/ - - -/* An object to save header lines. */ -struct header_s -{ - struct header_s *next; - char *value; /* The value of the header (malloced). */ - char name[1]; /* The name of the header (canonicalized). */ -}; -typedef struct header_s *header_t; - - -/* Our handle context. */ -struct http_context_s -{ - unsigned int status_code; - int sock; - unsigned int in_data:1; - unsigned int is_http_0_9:1; - estream_t fp_read; - estream_t fp_write; - void *write_cookie; - void *read_cookie; - void *tls_context; - parsed_uri_t uri; - http_req_t req_type; - char *buffer; /* Line buffer. */ - size_t buffer_size; - unsigned int flags; - header_t headers; /* Received headers. */ -}; - - - - -#if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP) - -#if GNUPG_MAJOR_VERSION == 1 -#define REQ_WINSOCK_MAJOR 1 -#define REQ_WINSOCK_MINOR 1 -#else -#define REQ_WINSOCK_MAJOR 2 -#define REQ_WINSOCK_MINOR 2 -#endif - - -static void -deinit_sockets (void) -{ - WSACleanup(); -} - -static void -init_sockets (void) -{ - static int initialized; - static WSADATA wsdata; - - if (initialized) - return; - - if ( WSAStartup( MAKEWORD (REQ_WINSOCK_MINOR, REQ_WINSOCK_MAJOR), &wsdata ) ) - { - log_error ("error initializing socket library: ec=%d\n", - (int)WSAGetLastError () ); - return; - } - if ( LOBYTE(wsdata.wVersion) != REQ_WINSOCK_MAJOR - || HIBYTE(wsdata.wVersion) != REQ_WINSOCK_MINOR ) - { - log_error ("socket library version is %x.%x - but %d.%d needed\n", - LOBYTE(wsdata.wVersion), HIBYTE(wsdata.wVersion), - REQ_WINSOCK_MAJOR, REQ_WINSOCK_MINOR); - WSACleanup(); - return; - } - atexit ( deinit_sockets ); - initialized = 1; -} -#endif /*HAVE_W32_SYSTEM && !HTTP_NO_WSASTARTUP*/ - - - -/* - * Helper function to create an HTTP header with hex encoded data. A - * new buffer is returned. This buffer is the concatenation of the - * string PREFIX, the hex-encoded DATA of length LEN and the string - * SUFFIX. On error NULL is returned and ERRNO set. - */ -static char * -make_header_line (const char *prefix, const char *suffix, - const void *data, size_t len ) -{ - static unsigned char bintoasc[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - const unsigned int *s = data; - char *buffer, *p; - - buffer = xtrymalloc (strlen (prefix) + (len+2)/3*4 + strlen (suffix) + 1); - if (!buffer) - return NULL; - p = stpcpy (buffer, prefix); - for ( ; len >= 3 ; len -= 3, s += 3 ) - { - *p++ = bintoasc[(s[0] >> 2) & 077]; - *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077]; - *p++ = bintoasc[(((s[1]<<2)&074)|((s[2]>>6)&03))&077]; - *p++ = bintoasc[s[2]&077]; - } - if ( len == 2 ) - { - *p++ = bintoasc[(s[0] >> 2) & 077]; - *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077]; - *p++ = bintoasc[((s[1]<<2)&074)]; - *p++ = '='; - } - else if ( len == 1 ) - { - *p++ = bintoasc[(s[0] >> 2) & 077]; - *p++ = bintoasc[(s[0] <<4)&060]; - *p++ = '='; - *p++ = '='; - } - strcpy (p, suffix); - return buffer; -} - - - - -void -http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) ) -{ -#ifdef HTTP_USE_GNUTLS - tls_callback = (gpg_error_t (*) (http_t, gnutls_session_t, int))cb; -#else - (void)cb; -#endif -} - - - -/* Start a HTTP retrieval and return on success in R_HD a context - pointer for completing the the request and to wait for the - response. */ -gpg_error_t -http_open (http_t *r_hd, http_req_t reqtype, const char *url, - const char *auth, unsigned int flags, const char *proxy, - void *tls_context) -{ - gpg_error_t err; - http_t hd; - - *r_hd = NULL; - - if (!(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST)) - return gpg_error (GPG_ERR_INV_ARG); - - /* Make need_header default unless ignore_cl is set. We might want - to drop the need_header entirely. */ - if (!(flags & HTTP_FLAG_IGNORE_CL)) - flags |= HTTP_FLAG_NEED_HEADER; - - /* Create the handle. */ - hd = xtrycalloc (1, sizeof *hd); - if (!hd) - return gpg_error_from_syserror (); - hd->sock = -1; - hd->req_type = reqtype; - hd->flags = flags; - hd->tls_context = tls_context; - - err = http_parse_uri (&hd->uri, url); - if (!err) - err = send_request (hd, auth, proxy); - - if (err) - { - if (!hd->fp_read && !hd->fp_write && hd->sock != -1) - sock_close (hd->sock); - if (hd->fp_read) - es_fclose (hd->fp_read); - if (hd->fp_write) - es_fclose (hd->fp_write); - http_release_parsed_uri (hd->uri); - xfree (hd); - } - else - *r_hd = hd; - return err; -} - - -void -http_start_data (http_t hd) -{ - if (!hd->in_data) - { - es_fputs ("\r\n", hd->fp_write); - es_fflush (hd->fp_write); - hd->in_data = 1; - } - else - es_fflush (hd->fp_write); -} - - -gpg_error_t -http_wait_response (http_t hd) -{ - gpg_error_t err; - cookie_t cookie; - - /* Make sure that we are in the data. */ - http_start_data (hd); - - cookie = hd->write_cookie; - if (!cookie) - return gpg_error (GPG_ERR_INTERNAL); - - /* Close the write stream but keep the socket open. */ - cookie->keep_socket = 1; - es_fclose (hd->fp_write); - hd->fp_write = NULL; - hd->write_cookie = NULL; - - /* Shutdown one end of the socket is desired. As per HTTP/1.0 this - is not required but some very old servers (e.g. the original pksd - key server didn't worked without it. */ - if ((hd->flags & HTTP_FLAG_SHUTDOWN)) - shutdown (hd->sock, 1); - hd->in_data = 0; - - /* Create a new cookie and a stream for reading. */ - cookie = xtrycalloc (1, sizeof *cookie); - if (!cookie) - return gpg_error_from_syserror (); - cookie->fd = hd->sock; - if (hd->uri->use_tls) - cookie->tls_session = hd->tls_context; - - hd->read_cookie = cookie; - hd->fp_read = es_fopencookie (cookie, "r", cookie_functions); - if (!hd->fp_read) - { - xfree (cookie); - hd->read_cookie = NULL; - return gpg_error_from_syserror (); - } - - err = parse_response (hd); - return err; -} - - -/* Convenience function to send a request and wait for the response. - Closes the handle on error. If PROXY is not NULL, this value will - be used as an HTTP proxy and any enabled $http_proxy gets - ignored. */ -gpg_error_t -http_open_document (http_t *r_hd, const char *document, - const char *auth, unsigned int flags, const char *proxy, - void *tls_context) -{ - gpg_error_t err; - - err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags, - proxy, tls_context); - if (err) - return err; - - err = http_wait_response (*r_hd); - if (err) - http_close (*r_hd, 0); - - return err; -} - - -void -http_close (http_t hd, int keep_read_stream) -{ - if (!hd) - return; - if (!hd->fp_read && !hd->fp_write && hd->sock != -1) - sock_close (hd->sock); - if (hd->fp_read && !keep_read_stream) - es_fclose (hd->fp_read); - if (hd->fp_write) - es_fclose (hd->fp_write); - http_release_parsed_uri (hd->uri); - while (hd->headers) - { - header_t tmp = hd->headers->next; - xfree (hd->headers->value); - xfree (hd->headers); - hd->headers = tmp; - } - xfree (hd->buffer); - xfree (hd); -} - - -estream_t -http_get_read_ptr (http_t hd) -{ - return hd?hd->fp_read:NULL; -} - -estream_t -http_get_write_ptr (http_t hd) -{ - return hd?hd->fp_write:NULL; -} - -unsigned int -http_get_status_code (http_t hd) -{ - return hd?hd->status_code:0; -} - - - -/* - * Parse an URI and put the result into the newly allocated RET_URI. - * The caller must always use release_parsed_uri() to releases the - * resources (even on error). - */ -gpg_error_t -http_parse_uri (parsed_uri_t * ret_uri, const char *uri) -{ - *ret_uri = xcalloc (1, sizeof **ret_uri + strlen (uri)); - strcpy ((*ret_uri)->buffer, uri); - return do_parse_uri (*ret_uri, 0); -} - -void -http_release_parsed_uri (parsed_uri_t uri) -{ - if (uri) - { - uri_tuple_t r, r2; - - for (r = uri->query; r; r = r2) - { - r2 = r->next; - xfree (r); - } - xfree (uri); - } -} - - -static gpg_error_t -do_parse_uri (parsed_uri_t uri, int only_local_part) -{ - uri_tuple_t *tail; - char *p, *p2, *p3, *pp; - int n; - - p = uri->buffer; - n = strlen (uri->buffer); - - /* Initialize all fields to an empty string or an empty list. */ - uri->scheme = uri->host = uri->path = p + n; - uri->port = 0; - uri->params = uri->query = NULL; - uri->use_tls = 0; - - /* A quick validity check. */ - if (strspn (p, VALID_URI_CHARS) != n) - return gpg_error (GPG_ERR_BAD_URI); /* Invalid characters found. */ - - if (!only_local_part) - { - /* Find the scheme. */ - if (!(p2 = strchr (p, ':')) || p2 == p) - return gpg_error (GPG_ERR_BAD_URI); /* No scheme. */ - *p2++ = 0; - for (pp=p; *pp; pp++) - *pp = tolower (*(unsigned char*)pp); - uri->scheme = p; - if (!strcmp (uri->scheme, "http")) - uri->port = 80; -#ifdef HTTP_USE_GNUTLS - else if (!strcmp (uri->scheme, "https")) - { - uri->port = 443; - uri->use_tls = 1; - } -#endif - else - return gpg_error (GPG_ERR_INV_URI); /* Unsupported scheme */ - - p = p2; - - /* Find the hostname */ - if (*p != '/') - return gpg_error (GPG_ERR_INV_URI); /* Does not start with a slash. */ - - p++; - if (*p == '/') /* There seems to be a hostname. */ - { - p++; - if ((p2 = strchr (p, '/'))) - *p2++ = 0; - - /* Check for username/password encoding */ - if ((p3 = strchr (p, '@'))) - { - uri->auth = p; - *p3++ = '\0'; - p = p3; - } - - for (pp=p; *pp; pp++) - *pp = tolower (*(unsigned char*)pp); - uri->host = p; - if ((p3 = strchr (p, ':'))) - { - *p3++ = 0; - uri->port = atoi (p3); - } - - uri->host = p; - if ((n = remove_escapes (uri->host)) < 0) - return gpg_error (GPG_ERR_BAD_URI); - if (n != strlen (p)) - return gpg_error (GPG_ERR_BAD_URI); /* Hostname incudes a Nul. */ - p = p2 ? p2 : NULL; - } - } /* End global URI part. */ - - /* Parse the pathname part */ - if (!p || !*p) - return 0; /* We don't have a path. Okay. */ - - /* TODO: Here we have to check params. */ - - /* Do we have a query part? */ - if ((p2 = strchr (p, '?'))) - *p2++ = 0; - - uri->path = p; - if ((n = remove_escapes (p)) < 0) - return gpg_error (GPG_ERR_BAD_URI); - if (n != strlen (p)) - return gpg_error (GPG_ERR_BAD_URI); /* Path includes a Nul. */ - p = p2 ? p2 : NULL; - - if (!p || !*p) - return 0; /* We don't have a query string. Okay. */ - - /* Now parse the query string. */ - tail = &uri->query; - for (;;) - { - uri_tuple_t elem; - - if ((p2 = strchr (p, '&'))) - *p2++ = 0; - if (!(elem = parse_tuple (p))) - return gpg_error (GPG_ERR_BAD_URI); - *tail = elem; - tail = &elem->next; - - if (!p2) - break; /* Ready. */ - p = p2; - } - - return 0; -} - - -/* - * Remove all %xx escapes; this is done in-place. Returns: New length - * of the string. - */ -static int -remove_escapes (char *string) -{ - int n = 0; - unsigned char *p, *s; - - for (p = s = (unsigned char*)string; *s; s++) - { - if (*s == '%') - { - if (s[1] && s[2] && isxdigit (s[1]) && isxdigit (s[2])) - { - s++; - *p = *s >= '0' && *s <= '9' ? *s - '0' : - *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10; - *p <<= 4; - s++; - *p |= *s >= '0' && *s <= '9' ? *s - '0' : - *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10; - p++; - n++; - } - else - { - *p++ = *s++; - if (*s) - *p++ = *s++; - if (*s) - *p++ = *s++; - if (*s) - *p = 0; - return -1; /* Bad URI. */ - } - } - else - { - *p++ = *s; - n++; - } - } - *p = 0; /* Make sure to keep a string terminator. */ - return n; -} - - -static int -insert_escapes (char *buffer, const char *string, - const char *special) -{ - const unsigned char *s = (const unsigned char*)string; - int n = 0; - - for (; *s; s++) - { - if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s)) - { - if (buffer) - *(unsigned char*)buffer++ = *s; - n++; - } - else - { - if (buffer) - { - sprintf (buffer, "%%%02X", *s); - buffer += 3; - } - n += 3; - } - } - return n; -} - - -/* Allocate a new string from STRING using standard HTTP escaping as - well as escaping of characters given in SPECIALS. A common pattern - for SPECIALS is "%;?&=". However it depends on the needs, for - example "+" and "/: often needs to be escaped too. Returns NULL on - failure and sets ERRNO. */ -char * -http_escape_string (const char *string, const char *specials) -{ - int n; - char *buf; - - n = insert_escapes (NULL, string, specials); - buf = xtrymalloc (n+1); - if (buf) - { - insert_escapes (buf, string, specials); - buf[n] = 0; - } - return buf; -} - - - -static uri_tuple_t -parse_tuple (char *string) -{ - char *p = string; - char *p2; - int n; - uri_tuple_t tuple; - - if ((p2 = strchr (p, '='))) - *p2++ = 0; - if ((n = remove_escapes (p)) < 0) - return NULL; /* Bad URI. */ - if (n != strlen (p)) - return NULL; /* Name with a Nul in it. */ - tuple = xtrycalloc (1, sizeof *tuple); - if (!tuple) - return NULL; /* Out of core. */ - tuple->name = p; - if (!p2) /* We have only the name, so we assume an empty value string. */ - { - tuple->value = p + strlen (p); - tuple->valuelen = 0; - tuple->no_value = 1; /* Explicitly mark that we have seen no '='. */ - } - else /* Name and value. */ - { - if ((n = remove_escapes (p2)) < 0) - { - xfree (tuple); - return NULL; /* Bad URI. */ - } - tuple->value = p2; - tuple->valuelen = n; - } - return tuple; -} - - -/* - * Send a HTTP request to the server - * Returns 0 if the request was successful - */ -static gpg_error_t -send_request (http_t hd, const char *auth, const char *proxy) -{ - gnutls_session_t tls_session; - gpg_error_t err; - const char *server; - char *request, *p; - unsigned short port; - const char *http_proxy = NULL; - char *proxy_authstr = NULL; - char *authstr = NULL; - int save_errno; - cookie_t cookie; - - - tls_session = hd->tls_context; - if (hd->uri->use_tls && !tls_session) - { - log_error ("TLS requested but no GNUTLS context provided\n"); - return gpg_error (GPG_ERR_INTERNAL); - } - - server = *hd->uri->host ? hd->uri->host : "localhost"; - port = hd->uri->port ? hd->uri->port : 80; - - if ( (proxy && *proxy) - || ( (hd->flags & HTTP_FLAG_TRY_PROXY) - && (http_proxy = getenv (HTTP_PROXY_ENV)) - && *http_proxy )) - { - parsed_uri_t uri; - - if (proxy) - http_proxy = proxy; - - err = http_parse_uri (&uri, http_proxy); - if (err) - { - log_error ("invalid HTTP proxy (%s): %s\n", - http_proxy, gpg_strerror (err)); - http_release_parsed_uri (uri); - return gpg_error (GPG_ERR_CONFIGURATION); - - } - - if (uri->auth) - { - remove_escapes (uri->auth); - proxy_authstr = make_header_line ("Proxy-Authorization: Basic ", - "\r\n", - uri->auth, strlen(uri->auth)); - if (!proxy_authstr) - { - err = gpg_error_from_syserror (); - http_release_parsed_uri (uri); - return err; - } - } - - hd->sock = connect_server (*uri->host ? uri->host : "localhost", - uri->port ? uri->port : 80, - hd->flags, hd->uri->scheme); - save_errno = errno; - http_release_parsed_uri (uri); - } - else - { - hd->sock = connect_server (server, port, hd->flags, hd->uri->scheme); - save_errno = errno; - } - - if (hd->sock == -1) - { - xfree (proxy_authstr); - return (save_errno - ? gpg_error_from_errno (save_errno) - : gpg_error (GPG_ERR_NOT_FOUND)); - } - -#ifdef HTTP_USE_GNUTLS - if (hd->uri->use_tls) - { - int rc; - - gnutls_transport_set_ptr (tls_session, (gnutls_transport_ptr_t)hd->sock); - do - { - rc = gnutls_handshake (tls_session); - } - while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN); - if (rc < 0) - { - log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc)); - xfree (proxy_authstr); - return gpg_error (GPG_ERR_NETWORK); - } - - if (tls_callback) - { - err = tls_callback (hd, tls_session, 0); - if (err) - { - log_info ("TLS connection authentication failed: %s\n", - gpg_strerror (err)); - xfree (proxy_authstr); - return err; - } - } - } -#endif /*HTTP_USE_GNUTLS*/ - - if (auth || hd->uri->auth) - { - char *myauth; - - if (auth) - { - myauth = xtrystrdup (auth); - if (!myauth) - { - xfree (proxy_authstr); - return gpg_error_from_syserror (); - } - remove_escapes (myauth); - } - else - { - remove_escapes (hd->uri->auth); - myauth = hd->uri->auth; - } - - authstr = make_header_line ("Authorization: Basic %s", "\r\n", - myauth, strlen (myauth)); - if (auth) - xfree (myauth); - - if (!authstr) - { - xfree (proxy_authstr); - return gpg_error_from_syserror (); - } - } - - p = build_rel_path (hd->uri); - if (!p) - return gpg_error_from_syserror (); - - if (http_proxy && *http_proxy) - { - request = es_asprintf - ("%s http://%s:%hu%s%s HTTP/1.0\r\n%s%s", - hd->req_type == HTTP_REQ_GET ? "GET" : - hd->req_type == HTTP_REQ_HEAD ? "HEAD" : - hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS", - server, port, *p == '/' ? "" : "/", p, - authstr ? authstr : "", - proxy_authstr ? proxy_authstr : ""); - } - else - { - char portstr[35]; - - if (port == 80) - *portstr = 0; - else - snprintf (portstr, sizeof portstr, ":%u", port); - - request = es_asprintf - ("%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s", - hd->req_type == HTTP_REQ_GET ? "GET" : - hd->req_type == HTTP_REQ_HEAD ? "HEAD" : - hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS", - *p == '/' ? "" : "/", p, server, portstr, - authstr? authstr:""); - } - xfree (p); - if (!request) - { - err = gpg_error_from_syserror (); - xfree (authstr); - xfree (proxy_authstr); - return err; - } - - /* First setup estream so that we can write even the first line - using estream. This is also required for the sake of gnutls. */ - cookie = xtrycalloc (1, sizeof *cookie); - if (!cookie) - { - err = gpg_error_from_syserror (); - goto leave; - } - cookie->fd = hd->sock; - hd->write_cookie = cookie; - if (hd->uri->use_tls) - cookie->tls_session = tls_session; - hd->fp_write = es_fopencookie (cookie, "w", cookie_functions); - if (!hd->fp_write) - { - xfree (cookie); - hd->write_cookie = NULL; - err = gpg_error_from_syserror (); - } - else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write)) - err = gpg_error_from_syserror (); - else - err = 0; - - leave: - es_free (request); - xfree (authstr); - xfree (proxy_authstr); - - return err; -} - - -/* - * Build the relative path from the parsed URI. Minimal - * implementation. May return NULL in case of memory failure; errno - * is then set accordingly. - */ -static char * -build_rel_path (parsed_uri_t uri) -{ - uri_tuple_t r; - char *rel_path, *p; - int n; - - /* Count the needed space. */ - n = insert_escapes (NULL, uri->path, "%;?&"); - /* TODO: build params. */ - for (r = uri->query; r; r = r->next) - { - n++; /* '?'/'&' */ - n += insert_escapes (NULL, r->name, "%;?&="); - if (!r->no_value) - { - n++; /* '=' */ - n += insert_escapes (NULL, r->value, "%;?&="); - } - } - n++; - - /* Now allocate and copy. */ - p = rel_path = xtrymalloc (n); - if (!p) - return NULL; - n = insert_escapes (p, uri->path, "%;?&"); - p += n; - /* TODO: add params. */ - for (r = uri->query; r; r = r->next) - { - *p++ = r == uri->query ? '?' : '&'; - n = insert_escapes (p, r->name, "%;?&="); - p += n; - if (!r->no_value) - { - *p++ = '='; - /* TODO: Use valuelen. */ - n = insert_escapes (p, r->value, "%;?&="); - p += n; - } - } - *p = 0; - return rel_path; -} - - -/* Transform a header name into a standard capitalized format; e.g. - "Content-Type". Conversion stops at the colon. As usual we don't - use the localized versions of ctype.h. */ -static void -capitalize_header_name (char *name) -{ - int first = 1; - - for (; *name && *name != ':'; name++) - { - if (*name == '-') - first = 1; - else if (first) - { - if (*name >= 'a' && *name <= 'z') - *name = *name - 'a' + 'A'; - first = 0; - } - else if (*name >= 'A' && *name <= 'Z') - *name = *name - 'A' + 'a'; - } -} - - -/* Store an HTTP header line in LINE away. Line continuation is - supported as well as merging of headers with the same name. This - function may modify LINE. */ -static gpg_error_t -store_header (http_t hd, char *line) -{ - size_t n; - char *p, *value; - header_t h; - - n = strlen (line); - if (n && line[n-1] == '\n') - { - line[--n] = 0; - if (n && line[n-1] == '\r') - line[--n] = 0; - } - if (!n) /* we are never called to hit this. */ - return gpg_error (GPG_ERR_BUG); - if (*line == ' ' || *line == '\t') - { - /* Continuation. This won't happen too often as it is not - recommended. We use a straightforward implementaion. */ - if (!hd->headers) - return gpg_error (GPG_ERR_PROTOCOL_VIOLATION); - n += strlen (hd->headers->value); - p = xtrymalloc (n+1); - if (!p) - return gpg_error_from_syserror (); - strcpy (stpcpy (p, hd->headers->value), line); - xfree (hd->headers->value); - hd->headers->value = p; - return 0; - } - - capitalize_header_name (line); - p = strchr (line, ':'); - if (!p) - return gpg_error (GPG_ERR_PROTOCOL_VIOLATION); - *p++ = 0; - while (*p == ' ' || *p == '\t') - p++; - value = p; - - for (h=hd->headers; h; h = h->next) - if ( !strcmp (h->name, line) ) - break; - if (h) - { - /* We have already seen a line with that name. Thus we assume - it is a comma separated list and merge them. */ - p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1); - if (!p) - return gpg_error_from_syserror (); - strcpy (stpcpy (stpcpy (p, h->value), ","), value); - xfree (h->value); - h->value = p; - return 0; - } - - /* Append a new header. */ - h = xtrymalloc (sizeof *h + strlen (line)); - if (!h) - return gpg_error_from_syserror (); - strcpy (h->name, line); - h->value = xtrymalloc (strlen (value)+1); - if (!h->value) - { - xfree (h); - return gpg_error_from_syserror (); - } - strcpy (h->value, value); - h->next = hd->headers; - hd->headers = h; - - return 0; -} - - -/* Return the header NAME from the last response. The returned value - is valid as along as HD has not been closed and no othe request has - been send. If the header was not found, NULL is returned. Name - must be canonicalized, that is the first letter of each dash - delimited part must be uppercase and all other letters lowercase. - Note that the context must have been opened with the - HTTP_FLAG_NEED_HEADER. */ -const char * -http_get_header (http_t hd, const char *name) -{ - header_t h; - - for (h=hd->headers; h; h = h->next) - if ( !strcmp (h->name, name) ) - return h->value; - return NULL; -} - - - -/* - * Parse the response from a server. - * Returns: Errorcode and sets some files in the handle - */ -static gpg_error_t -parse_response (http_t hd) -{ - char *line, *p, *p2; - size_t maxlen, len; - cookie_t cookie = hd->read_cookie; - const char *s; - - /* Delete old header lines. */ - while (hd->headers) - { - header_t tmp = hd->headers->next; - xfree (hd->headers->value); - xfree (hd->headers); - hd->headers = tmp; - } - - /* Wait for the status line. */ - do - { - maxlen = MAX_LINELEN; - len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen); - line = hd->buffer; - if (!line) - return gpg_error_from_syserror (); /* Out of core. */ - if (!maxlen) - return gpg_error (GPG_ERR_TRUNCATED); /* Line has been truncated. */ - if (!len) - return gpg_error (GPG_ERR_EOF); - if ( (hd->flags & HTTP_FLAG_LOG_RESP) ) - log_info ("RESP: `%.*s'\n", - (int)strlen(line)-(*line&&line[1]?2:0),line); - } - while (!*line); - - if ((p = strchr (line, '/'))) - *p++ = 0; - if (!p || strcmp (line, "HTTP")) - return 0; /* Assume http 0.9. */ - - if ((p2 = strpbrk (p, " \t"))) - { - *p2++ = 0; - p2 += strspn (p2, " \t"); - } - if (!p2) - return 0; /* Also assume http 0.9. */ - p = p2; - /* TODO: Add HTTP version number check. */ - if ((p2 = strpbrk (p, " \t"))) - *p2++ = 0; - if (!isdigit ((unsigned int)p[0]) || !isdigit ((unsigned int)p[1]) - || !isdigit ((unsigned int)p[2]) || p[3]) - { - /* Malformed HTTP status code - assume http 0.9. */ - hd->is_http_0_9 = 1; - hd->status_code = 200; - return 0; - } - hd->status_code = atoi (p); - - /* Skip all the header lines and wait for the empty line. */ - do - { - maxlen = MAX_LINELEN; - len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen); - line = hd->buffer; - if (!line) - return gpg_error_from_syserror (); /* Out of core. */ - /* Note, that we can silently ignore truncated lines. */ - if (!len) - return gpg_error (GPG_ERR_EOF); - /* Trim line endings of empty lines. */ - if ((*line == '\r' && line[1] == '\n') || *line == '\n') - *line = 0; - if ( (hd->flags & HTTP_FLAG_LOG_RESP) ) - log_info ("RESP: `%.*s'\n", - (int)strlen(line)-(*line&&line[1]?2:0),line); - if ( (hd->flags & HTTP_FLAG_NEED_HEADER) && *line ) - { - gpg_error_t err = store_header (hd, line); - if (err) - return err; - } - } - while (len && *line); - - cookie->content_length_valid = 0; - if (!(hd->flags & HTTP_FLAG_IGNORE_CL)) - { - s = http_get_header (hd, "Content-Length"); - if (s) - { - cookie->content_length_valid = 1; - cookie->content_length = counter_strtoul (s); - } - } - - return 0; -} - -#if 0 -static int -start_server () -{ - struct sockaddr_in mya; - struct sockaddr_in peer; - int fd, client; - fd_set rfds; - int addrlen; - int i; - - if ((fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) - { - log_error ("socket() failed: %s\n", strerror (errno)); - return -1; - } - i = 1; - if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (byte *) & i, sizeof (i))) - log_info ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno)); - - mya.sin_family = AF_INET; - memset (&mya.sin_addr, 0, sizeof (mya.sin_addr)); - mya.sin_port = htons (11371); - - if (bind (fd, (struct sockaddr *) &mya, sizeof (mya))) - { - log_error ("bind to port 11371 failed: %s\n", strerror (errno)); - sock_close (fd); - return -1; - } - - if (listen (fd, 5)) - { - log_error ("listen failed: %s\n", strerror (errno)); - sock_close (fd); - return -1; - } - - for (;;) - { - FD_ZERO (&rfds); - FD_SET (fd, &rfds); - - if (select (fd + 1, &rfds, NULL, NULL, NULL) <= 0) - continue; /* ignore any errors */ - - if (!FD_ISSET (fd, &rfds)) - continue; - - addrlen = sizeof peer; - client = accept (fd, (struct sockaddr *) &peer, &addrlen); - if (client == -1) - continue; /* oops */ - - log_info ("connect from %s\n", inet_ntoa (peer.sin_addr)); - - fflush (stdout); - fflush (stderr); - if (!fork ()) - { - int c; - FILE *fp; - - fp = fdopen (client, "r"); - while ((c = getc (fp)) != EOF) - putchar (c); - fclose (fp); - exit (0); - } - sock_close (client); - } - - - return 0; -} -#endif - -/* Actually connect to a server. Returns the file descripto or -1 on - error. ERRNO is set on error. */ -static int -connect_server (const char *server, unsigned short port, - unsigned int flags, const char *srvtag) -{ - int sock = -1; - int srvcount = 0; - int hostfound = 0; - int srv, connected; - int last_errno = 0; - struct srventry *serverlist = NULL; - -#ifdef HAVE_W32_SYSTEM - unsigned long inaddr; - -#ifndef HTTP_NO_WSASTARTUP - init_sockets (); -#endif - /* Win32 gethostbyname doesn't handle IP addresses internally, so we - try inet_addr first on that platform only. */ - inaddr = inet_addr(server); - if ( inaddr != INADDR_NONE ) - { - struct sockaddr_in addr; - - memset(&addr,0,sizeof(addr)); - - sock = socket(AF_INET,SOCK_STREAM,0); - if ( sock==INVALID_SOCKET ) - { - log_error("error creating socket: ec=%d\n",(int)WSAGetLastError()); - return -1; - } - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - memcpy (&addr.sin_addr,&inaddr,sizeof(inaddr)); - - if (!connect (sock,(struct sockaddr *)&addr,sizeof(addr)) ) - return sock; - sock_close(sock); - return -1; - } -#endif /*HAVE_W32_SYSTEM*/ - -#ifdef USE_DNS_SRV - /* Do the SRV thing */ - if ((flags & HTTP_FLAG_TRY_SRV) && srvtag) - { - /* We're using SRV, so append the tags. */ - if (1+strlen (srvtag) + 6 + strlen (server) + 1 <= MAXDNAME) - { - char srvname[MAXDNAME]; - - stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag), - "._tcp."), server); - srvcount = getsrv (srvname, &serverlist); - } - } -#else /*!USE_DNS_SRV*/ - (void)flags; - (void)srvtag; -#endif /*!USE_DNS_SRV*/ - - if (!serverlist) - { - /* Either we're not using SRV, or the SRV lookup failed. Make - up a fake SRV record. */ - serverlist = xtrycalloc (1, sizeof *serverlist); - if (!serverlist) - return -1; /* Out of core. */ - serverlist->port = port; - strncpy (serverlist->target, server, MAXDNAME); - serverlist->target[MAXDNAME-1] = '\0'; - srvcount = 1; - } - -#ifdef HAVE_GETADDRINFO - connected = 0; - for (srv=0; srv < srvcount && !connected; srv++) - { - struct addrinfo hints, *res, *ai; - char portstr[35]; - - sprintf (portstr, "%hu", port); - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_STREAM; - if (getaddrinfo (serverlist[srv].target, portstr, &hints, &res)) - continue; /* Not found - try next one. */ - hostfound = 1; - - for (ai = res; ai && !connected; ai = ai->ai_next) - { - if (sock != -1) - sock_close (sock); - sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sock == -1) - { - int save_errno = errno; - log_error ("error creating socket: %s\n", strerror (errno)); - freeaddrinfo (res); - xfree (serverlist); - errno = save_errno; - return -1; - } - - if (connect (sock, ai->ai_addr, ai->ai_addrlen)) - last_errno = errno; - else - connected = 1; - } - freeaddrinfo (res); - } -#else /* !HAVE_GETADDRINFO */ - connected = 0; - for (srv=0; srv < srvcount && !connected; srv++) - { - int i; - struct hostent *host = NULL; - struct sockaddr_in addr; - - /* Note: This code is not thread-safe. */ - - memset (&addr, 0, sizeof (addr)); - host = gethostbyname (serverlist[srv].target); - if (!host) - continue; - hostfound = 1; - - if (sock != -1) - sock_close (sock); - sock = socket (host->h_addrtype, SOCK_STREAM, 0); - if (sock == -1) - { - log_error (_("error creating socket: %s\n"), strerror (errno)); - xfree (serverlist); - return -1; - } - - addr.sin_family = host->h_addrtype; - if (addr.sin_family != AF_INET) - { - log_error ("unknown address family for `%s'\n", - serverlist[srv].target); - xfree (serverlist); - return -1; - } - addr.sin_port = htons (serverlist[srv].port); - if (host->h_length != 4) - { - log_error ("illegal address length for `%s'\n", - serverlist[srv].target); - xfree (serverlist); - return -1; - } - - /* Try all A records until one responds. */ - for (i = 0; host->h_addr_list[i] && !connected; i++) - { - memcpy (&addr.sin_addr, host->h_addr_list[i], host->h_length); - if (connect (sock, (struct sockaddr *) &addr, sizeof (addr))) - last_errno = errno; - else - { - connected = 1; - break; - } - } - } -#endif /* !HAVE_GETADDRINFO */ - - xfree (serverlist); - - if (!connected) - { -#ifdef HAVE_W32_SYSTEM - log_error ("can't connect to `%s': %s%sec=%d\n", - server, - hostfound? "":_("host not found"), - hostfound? "":" - ", (int)WSAGetLastError()); -#else - log_error ("can't connect to `%s': %s\n", - server, - hostfound? strerror (last_errno):"host not found"); -#endif - if (sock != -1) - sock_close (sock); - errno = last_errno; - return -1; - } - return sock; -} - - - - -/* Read handler for estream. */ -static ssize_t -cookie_read (void *cookie, void *buffer, size_t size) -{ - cookie_t c = cookie; - int nread; - - if (c->content_length_valid) - { - if (!c->content_length) - return 0; /* EOF */ - if (c->content_length < size) - size = c->content_length; - } - -#ifdef HTTP_USE_GNUTLS - if (c->tls_session) - { - again: - nread = gnutls_record_recv (c->tls_session, buffer, size); - if (nread < 0) - { - if (nread == GNUTLS_E_INTERRUPTED) - goto again; - if (nread == GNUTLS_E_AGAIN) - { - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = 50000; - select (0, NULL, NULL, NULL, &tv); - goto again; - } - if (nread == GNUTLS_E_REHANDSHAKE) - goto again; /* A client is allowed to just ignore this request. */ - log_info ("TLS network read failed: %s\n", gnutls_strerror (nread)); - errno = EIO; - return -1; - } - } - else -#endif /*HTTP_USE_GNUTLS*/ - { - do - { - nread = pth_read (c->fd, buffer, size); - } - while (nread == -1 && errno == EINTR); - } - - if (c->content_length_valid && nread > 0) - { - if (nread < c->content_length) - c->content_length -= nread; - else - c->content_length = 0; - } - - return nread; -} - -/* Write handler for estream. */ -static ssize_t -cookie_write (void *cookie, const void *buffer, size_t size) -{ - cookie_t c = cookie; - int nwritten = 0; - -#ifdef HTTP_USE_GNUTLS - if (c->tls_session) - { - int nleft = size; - while (nleft > 0) - { - nwritten = gnutls_record_send (c->tls_session, buffer, nleft); - if (nwritten <= 0) - { - if (nwritten == GNUTLS_E_INTERRUPTED) - continue; - if (nwritten == GNUTLS_E_AGAIN) - { - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = 50000; - select (0, NULL, NULL, NULL, &tv); - continue; - } - log_info ("TLS network write failed: %s\n", - gnutls_strerror (nwritten)); - errno = EIO; - return -1; - } - nleft -= nwritten; - buffer += nwritten; - } - } - else -#endif /*HTTP_USE_GNUTLS*/ - { - do - { - nwritten = pth_write (c->fd, buffer, size); - } - while (nwritten == -1 && errno == EINTR); - } - - return nwritten; -} - -/* Close handler for estream. */ -static int -cookie_close (void *cookie) -{ - cookie_t c = cookie; - - if (!c) - return 0; - -#ifdef HTTP_USE_GNUTLS - if (c->tls_session && !c->keep_socket) - { - /* This indicates that the read end has been closed. */ - gnutls_bye (c->tls_session, GNUTLS_SHUT_RDWR); - } -#endif /*HTTP_USE_GNUTLS*/ - if (c->fd != -1 && !c->keep_socket) - sock_close (c->fd); - - xfree (c); - return 0; -} - - - - -/**** Test code ****/ -#ifdef TEST - -static gpg_error_t -verify_callback (http_t hd, void *tls_context, int reserved) -{ - log_info ("verification of certificates skipped\n"); - return 0; -} - - - -/* static void */ -/* my_gnutls_log (int level, const char *text) */ -/* { */ -/* fprintf (stderr, "gnutls:L%d: %s", level, text); */ -/* } */ - -int -main (int argc, char **argv) -{ - int rc; - parsed_uri_t uri; - uri_tuple_t r; - http_t hd; - int c; - gnutls_session_t tls_session = NULL; -#ifdef HTTP_USE_GNUTLS - gnutls_certificate_credentials certcred; - const int certprio[] = { GNUTLS_CRT_X509, 0 }; -#endif /*HTTP_USE_GNUTLS*/ - header_t hdr; - - es_init (); - log_set_prefix ("http-test", 1 | 4); - if (argc == 1) - { - /*start_server (); */ - return 0; - } - - if (argc != 2) - { - fprintf (stderr, "usage: http-test uri\n"); - return 1; - } - argc--; - argv++; - -#ifdef HTTP_USE_GNUTLS - rc = gnutls_global_init (); - if (rc) - log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); - rc = gnutls_certificate_allocate_credentials (&certcred); - if (rc) - log_error ("gnutls_certificate_allocate_credentials failed: %s\n", - gnutls_strerror (rc)); -/* rc = gnutls_certificate_set_x509_trust_file */ -/* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */ -/* if (rc) */ -/* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */ -/* gnutls_strerror (rc)); */ - rc = gnutls_init (&tls_session, GNUTLS_CLIENT); - if (rc) - log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc)); - rc = gnutls_set_default_priority (tls_session); - if (rc) - log_error ("gnutls_set_default_priority failed: %s\n", - gnutls_strerror (rc)); - rc = gnutls_certificate_type_set_priority (tls_session, certprio); - if (rc) - log_error ("gnutls_certificate_type_set_priority failed: %s\n", - gnutls_strerror (rc)); - rc = gnutls_credentials_set (tls_session, GNUTLS_CRD_CERTIFICATE, certcred); - if (rc) - log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc)); -/* gnutls_global_set_log_function (my_gnutls_log); */ -/* gnutls_global_set_log_level (4); */ - - http_register_tls_callback (verify_callback); -#endif /*HTTP_USE_GNUTLS*/ - - rc = http_parse_uri (&uri, *argv); - if (rc) - { - log_error ("`%s': %s\n", *argv, gpg_strerror (rc)); - http_release_parsed_uri (uri); - return 1; - } - - printf ("Scheme: %s\n", uri->scheme); - printf ("Host : %s\n", uri->host); - printf ("Port : %u\n", uri->port); - printf ("Path : %s\n", uri->path); - for (r = uri->params; r; r = r->next) - { - printf ("Params: %s", r->name); - if (!r->no_value) - { - printf ("=%s", r->value); - if (strlen (r->value) != r->valuelen) - printf (" [real length=%d]", (int) r->valuelen); - } - putchar ('\n'); - } - for (r = uri->query; r; r = r->next) - { - printf ("Query : %s", r->name); - if (!r->no_value) - { - printf ("=%s", r->value); - if (strlen (r->value) != r->valuelen) - printf (" [real length=%d]", (int) r->valuelen); - } - putchar ('\n'); - } - http_release_parsed_uri (uri); - uri = NULL; - - rc = http_open_document (&hd, *argv, NULL, - HTTP_FLAG_NEED_HEADER, - NULL, tls_session); - if (rc) - { - log_error ("can't get `%s': %s\n", *argv, gpg_strerror (rc)); - return 1; - } - log_info ("open_http_document succeeded; status=%u\n", - http_get_status_code (hd)); - for (hdr = hd->headers; hdr; hdr = hdr->next) - printf ("HDR: %s: %s\n", hdr->name, hdr->value); - switch (http_get_status_code (hd)) - { - case 200: - while ((c = es_getc (http_get_read_ptr (hd))) != EOF) - putchar (c); - break; - case 301: - case 302: - printf ("Redirected to `%s'\n", http_get_header (hd, "Location")); - break; - } - http_close (hd, 0); - -#ifdef HTTP_USE_GNUTLS - gnutls_deinit (tls_session); - gnutls_certificate_free_credentials (certcred); - gnutls_global_deinit (); -#endif /*HTTP_USE_GNUTLS*/ - - return 0; -} -#endif /*TEST*/ - -/* -Local Variables: -compile-command: "gcc -I.. -I../gl -DTEST -DHAVE_CONFIG_H -Wall -O2 -g -o http-test http.c -L. -lcommon -L../jnlib -ljnlib -lgcrypt -lpth -lgnutls" -End: -*/ diff --git a/dirmngr/http.h b/dirmngr/http.h deleted file mode 100644 index 6e688b8d1..000000000 --- a/dirmngr/http.h +++ /dev/null @@ -1,109 +0,0 @@ -/* http.h - HTTP protocol handler - * Copyright (C) 1999, 2000, 2001, 2003, - * 2006 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ -#ifndef GNUPG_COMMON_HTTP_H -#define GNUPG_COMMON_HTTP_H - -#include <gpg-error.h> -#include "estream.h" - -struct uri_tuple_s { - struct uri_tuple_s *next; - const char *name; /* A pointer into name. */ - char *value; /* A pointer to value (a Nul is always appended). */ - size_t valuelen; /* The real length of the value; we need it - because the value may contain embedded Nuls. */ - int no_value; /* True if no value has been given in the URL. */ -}; -typedef struct uri_tuple_s *uri_tuple_t; - -struct parsed_uri_s -{ - /* All these pointers point into BUFFER; most stuff is not escaped. */ - char *scheme; /* Pointer to the scheme string (lowercase). */ - int use_tls; /* Whether TLS should be used. */ - char *auth; /* username/password for basic auth */ - char *host; /* Host (converted to lowercase). */ - unsigned short port; /* Port (always set if the host is set). */ - char *path; /* Path. */ - uri_tuple_t params; /* ";xxxxx" */ - uri_tuple_t query; /* "?xxx=yyy" */ - char buffer[1]; /* Buffer which holds a (modified) copy of the URI. */ -}; -typedef struct parsed_uri_s *parsed_uri_t; - -typedef enum - { - HTTP_REQ_GET = 1, - HTTP_REQ_HEAD = 2, - HTTP_REQ_POST = 3 - } -http_req_t; - -/* We put the flag values into an enum, so that gdb can display them. */ -enum - { - HTTP_FLAG_TRY_PROXY = 1, - HTTP_FLAG_SHUTDOWN = 2, - HTTP_FLAG_TRY_SRV = 4, - HTTP_FLAG_LOG_RESP = 8, - HTTP_FLAG_NEED_HEADER = 16, - HTTP_FLAG_IGNORE_CL = 32 - }; - -struct http_context_s; -typedef struct http_context_s *http_t; - -void http_register_tls_callback (gpg_error_t (*cb) (http_t, void *, int)); - -gpg_error_t http_parse_uri (parsed_uri_t *ret_uri, const char *uri); - -void http_release_parsed_uri (parsed_uri_t uri); - -gpg_error_t http_open (http_t *r_hd, http_req_t reqtype, - const char *url, - const char *auth, - unsigned int flags, - const char *proxy, - void *tls_context); - -void http_start_data (http_t hd); - -gpg_error_t http_wait_response (http_t hd); - -void http_close (http_t hd, int keep_read_stream); - -gpg_error_t http_open_document (http_t *r_hd, - const char *document, - const char *auth, - unsigned int flags, - const char *proxy, - void *tls_context); - -estream_t http_get_read_ptr (http_t hd); -estream_t http_get_write_ptr (http_t hd); -unsigned int http_get_status_code (http_t hd); -const char *http_get_header (http_t hd, const char *name); - -char *http_escape_string (const char *string, const char *specials); - - -#endif /*GNUPG_COMMON_HTTP_H*/ diff --git a/dirmngr/ocsp.c b/dirmngr/ocsp.c index a8db51d17..ec727f014 100644 --- a/dirmngr/ocsp.c +++ b/dirmngr/ocsp.c @@ -166,10 +166,8 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md, once_more: err = http_open (&http, HTTP_REQ_POST, url, NULL, - (opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0) - |HTTP_FLAG_NEED_HEADER, - opt.http_proxy, - NULL); + (opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0), + opt.http_proxy, NULL, NULL, NULL); if (err) { log_error (_("error connecting to `%s': %s\n"), url, gpg_strerror (err)); diff --git a/dirmngr/server.c b/dirmngr/server.c index a7b623cb1..ce0a5b3c8 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -1143,7 +1143,7 @@ static gpg_error_t cmd_listcrls (assuan_context_t ctx, char *line) { gpg_error_t err; - FILE *fp = assuan_get_data_fp (ctx); + estream_t fp = assuan_get_data_fp (ctx); (void)line; |