diff --git a/g10/ChangeLog b/g10/ChangeLog index f9f0e3c89..b82ceae28 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +Thu Apr 2 20:22:35 1998 Werner Koch (wk@isil.d.shuttle.de) + + * gpgd.c: New + Thu Apr 2 10:38:16 1998 Werner Koch (wk@isil.d.shuttle.de) * keygen.c (generate_keypair): Add valid_days stuff. diff --git a/g10/Makefile.am b/g10/Makefile.am index bbdb598a4..438acec19 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -6,7 +6,7 @@ OMIT_DEPENDENCIES = zlib.h zconf.h BUILT_SOURCES = g10maint.c needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a -bin_PROGRAMS = gpg gpgm +bin_PROGRAMS = gpg gpgm gpgd common_source = \ build-packet.c \ @@ -64,6 +64,10 @@ gpgm_SOURCES = g10maint.c \ dearmor.c \ $(common_source) +gpgd_SOURCES = gpgd.c \ + $(common_source) + + LDADD = @INTLLIBS@ $(needed_libs) @ZLIBS@ g10maint.c : g10.c diff --git a/g10/Makefile.in b/g10/Makefile.in index 9f6ff08eb..60aed6e28 100644 --- a/g10/Makefile.in +++ b/g10/Makefile.in @@ -98,7 +98,7 @@ OMIT_DEPENDENCIES = zlib.h zconf.h BUILT_SOURCES = g10maint.c needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a -bin_PROGRAMS = gpg gpgm +bin_PROGRAMS = gpg gpgm gpgd common_source = \ build-packet.c \ @@ -155,6 +155,9 @@ gpgm_SOURCES = g10maint.c \ dearmor.c \ $(common_source) +gpgd_SOURCES = gpgd.c \ + $(common_source) + LDADD = @INTLLIBS@ $(needed_libs) @ZLIBS@ mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs CONFIG_HEADER = ../config.h @@ -188,6 +191,16 @@ gpgm_LDADD = $(LDADD) gpgm_DEPENDENCIES = ../cipher/libcipher.a ../mpi/libmpi.a \ ../util/libutil.a gpgm_LDFLAGS = +gpgd_OBJECTS = gpgd.o build-packet.o compress.o free-packet.o getkey.o \ +pkclist.o skclist.o ringedit.o kbnode.o mainproc.o armor.o mdfilter.o \ +textfilter.o cipher.o elg.o dsa.o rsa.o openfile.o keyid.o trustdb.o \ +parse-packet.o passphrase.o pubkey-enc.o seckey-cert.o seskey.o \ +import.o export.o comment.o status.o sign.o plaintext.o encr-data.o \ +encode.o revoke.o keylist.o sig-check.o signal.o +gpgd_LDADD = $(LDADD) +gpgd_DEPENDENCIES = ../cipher/libcipher.a ../mpi/libmpi.a \ +../util/libutil.a +gpgd_LDFLAGS = CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ @@ -202,15 +215,16 @@ DEP_FILES = .deps/armor.P .deps/build-packet.P .deps/cipher.P \ .deps/comment.P .deps/compress.P .deps/dearmor.P .deps/decrypt.P \ .deps/dsa.P .deps/elg.P .deps/encode.P .deps/encr-data.P .deps/export.P \ .deps/free-packet.P .deps/g10.P .deps/g10maint .deps/g10maint.P \ -.deps/getkey.P .deps/import.P .deps/kbnode.P .deps/keygen.P \ -.deps/keyid.P .deps/keylist.P .deps/mainproc.P .deps/mdfilter.P \ -.deps/openfile.P .deps/parse-packet.P .deps/passphrase.P \ -.deps/pkclist.P .deps/plaintext.P .deps/pubkey-enc.P .deps/revoke.P \ -.deps/ringedit.P .deps/rsa.P .deps/seckey-cert.P .deps/seskey.P \ -.deps/sig-check.P .deps/sign.P .deps/signal.P .deps/skclist.P \ -.deps/status.P .deps/textfilter.P .deps/trustdb.P .deps/verify.P -SOURCES = $(gpg_SOURCES) $(gpgm_SOURCES) -OBJECTS = $(gpg_OBJECTS) $(gpgm_OBJECTS) +.deps/getkey.P .deps/gpgd.P .deps/import.P .deps/kbnode.P \ +.deps/keygen.P .deps/keyid.P .deps/keylist.P .deps/mainproc.P \ +.deps/mdfilter.P .deps/openfile.P .deps/parse-packet.P \ +.deps/passphrase.P .deps/pkclist.P .deps/plaintext.P .deps/pubkey-enc.P \ +.deps/revoke.P .deps/ringedit.P .deps/rsa.P .deps/seckey-cert.P \ +.deps/seskey.P .deps/sig-check.P .deps/sign.P .deps/signal.P \ +.deps/skclist.P .deps/status.P .deps/textfilter.P .deps/trustdb.P \ +.deps/verify.P +SOURCES = $(gpg_SOURCES) $(gpgm_SOURCES) $(gpgd_SOURCES) +OBJECTS = $(gpg_OBJECTS) $(gpgm_OBJECTS) $(gpgd_OBJECTS) default: all @@ -273,6 +287,10 @@ gpgm: $(gpgm_OBJECTS) $(gpgm_DEPENDENCIES) @rm -f gpgm $(LINK) $(gpgm_LDFLAGS) $(gpgm_OBJECTS) $(gpgm_LDADD) $(LIBS) +gpgd: $(gpgd_OBJECTS) $(gpgd_DEPENDENCIES) + @rm -f gpgd + $(LINK) $(gpgd_LDFLAGS) $(gpgd_OBJECTS) $(gpgd_LDADD) $(LIBS) + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) diff --git a/g10/gpgd.c b/g10/gpgd.c new file mode 100644 index 000000000..cb6adada0 --- /dev/null +++ b/g10/gpgd.c @@ -0,0 +1,300 @@ +/* ggpd.c - The GNUPG daemon (keyserver) + * Copyright (C) 1998 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 +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "cipher.h" +#include "options.h" +#include "main.h" + + +static ARGPARSE_OPTS opts[] = { + { 'v', "verbose", 0, "verbose" }, + { 501, "options" ,2, "read options from file"}, + { 502, "no-daemon", 0, "do not operate as a daemon" }, + { 510, "debug" ,4|16, "set debugging flags"}, + { 511, "debug-all" ,0, "enable full debugging"}, +{0} }; + + + +static char *build_list( const char *text, + const char * (*mapf)(int), int (*chkf)(int) ); +static void become_daemon(void); + +const char * +strusage( int level ) +{ + static char *digests, *pubkeys, *ciphers; + const char *p; + switch( level ) { + case 11: p = "gpgd (GNUPG)"; break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = + "Please report bugs to .\n"; + break; + case 1: + case 40: p = "Usage: gpgd [options] (-h for help)"; + break; + case 41: p = "Syntax: gpgd [options] [files]\n" + "GNUPG keyserver\n"; + break; + case 31: p = "\n"; break; + case 32: + if( !ciphers ) + ciphers = build_list("Supported ciphers: ", cipher_algo_to_string, + check_cipher_algo ); + p = ciphers; + break; + case 33: + if( !pubkeys ) + pubkeys = build_list("Supported pubkeys: ", pubkey_algo_to_string, + check_pubkey_algo ); + p = pubkeys; + break; + case 34: + if( !digests ) + digests = build_list("Supported digests: ", digest_algo_to_string, + check_digest_algo ); + p = digests; + break; + + default: p = default_strusage(level); + } + return p; +} + + +static char * +build_list( const char *text, const char * (*mapf)(int), int (*chkf)(int) ) +{ + int i; + const char *s; + size_t n=strlen(text)+2; + char *list, *p; + + for(i=1; i < 100; i++ ) + if( !chkf(i) && (s=mapf(i)) ) + n += strlen(s) + 2; + list = m_alloc( 21 + n ); *list = 0; + for(p=NULL, i=1; i < 100; i++ ) { + if( !chkf(i) && (s=mapf(i)) ) { + if( !p ) + p = stpcpy( list, text ); + else + p = stpcpy( p, ", "); + p = stpcpy(p, s ); + } + } + if( p ) + p = stpcpy(p, "\n" ); + return list; +} + + +static void +set_debug(void) +{ + if( opt.debug & DBG_MEMORY_VALUE ) + memory_debug_mode = 1; + if( opt.debug & DBG_MEMSTAT_VALUE ) + memory_stat_debug_mode = 1; + if( opt.debug & DBG_MPI_VALUE ) + mpi_debug_mode = 1; + if( opt.debug & DBG_CIPHER_VALUE ) + cipher_debug_mode = 1; + if( opt.debug & DBG_IOBUF_VALUE ) + iobuf_debug_mode = 1; +} + + +void +main( int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + int orig_argc; + char **orig_argv; + FILE *configfp = NULL; + char *configname = NULL; + unsigned configlineno; + int parse_debug = 0; + int default_config =1; + int daemon = 1; + + secmem_init( 0 ); /* disable use of secmem */ + log_set_name("gpgd"); + log_set_pid( getpid() ); + opt.compress = -1; /* defaults to standard compress level */ + opt.batch = 1; + + /* check wether we have a config file on the commandline */ + orig_argc = argc; + orig_argv = argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* do not remove the args */ + while( arg_parse( &pargs, opts) ) { + if( pargs.r_opt == 510 || pargs.r_opt == 511 ) + parse_debug++; + else if( pargs.r_opt == 501 ) { + /* yes there is one, so we do not try the default one, but + * read the option file when it is encountered at the commandline + */ + default_config = 0; + } + } + + if( default_config ) + configname = make_filename("/etc/gpgd.conf", NULL ); + + argc = orig_argc; + argv = orig_argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* do not remove the args */ + next_pass: + if( configname ) { + configlineno = 0; + configfp = fopen( configname, "r" ); + if( !configfp ) { + if( default_config ) { + if( parse_debug ) + log_info("note: no default option file '%s'\n", + configname ); + } + else { + log_error("option file '%s': %s\n", + configname, strerror(errno) ); + g10_exit(1); + } + m_free(configname); configname = NULL; + } + if( parse_debug && configname ) + log_info("reading options from '%s'\n", configname ); + default_config = 0; + } + + while( optfile_parse( configfp, configname, &configlineno, + &pargs, opts) ) { + switch( pargs.r_opt ) { + case 'v': opt.verbose++; break; + case 501: + if( !configfp ) { + m_free(configname); + configname = m_strdup(pargs.r.ret_str); + goto next_pass; + } + break; + case 502: daemon = 0; break; + case 510: opt.debug |= pargs.r.ret_ulong; break; + case 511: opt.debug = ~0; break; + default : pargs.err = configfp? 1:2; break; + } + } + if( configfp ) { + fclose( configfp ); + configfp = NULL; + m_free(configname); configname = NULL; + goto next_pass; + } + m_free( configname ); configname = NULL; + if( log_get_errorcount(0) ) + g10_exit(2); + + fprintf(stderr, "%s %s; %s\n", strusage(11), strusage(13), strusage(14) ); + fprintf(stderr, "%s\n", strusage(15) ); + + set_debug(); + if( daemon ) + become_daemon(); + + + + + g10_exit(0); +} + + +void +g10_exit( int rc ) +{ + secmem_term(); + rc = rc? rc : log_get_errorcount(0)? 2:0; + exit(rc ); +} + + +static void +become_daemon() +{ + long nfile; + int i, n; + int childpid; + + if( opt.verbose ) + log_info("becoming a daemon ...\n"); + fflush(NULL); + + /* FIXME: handle the TTY signals */ + + if( (childpid = fork()) == -1 ) + log_fatal("can't fork first child: %s\n", strerror(errno)); + else if( childpid > 0 ) + exit(0); /* terminate parent */ + + /* Disassociate from controlling terminal etc. */ + if( setsid() == -1 ) + log_fatal("setsid() failed: %s\n", strerror(errno) ); + + log_set_pid( getpid() ); + /* close all files but not the log files */ + if( (nfile=sysconf( _SC_OPEN_MAX )) < 0 ) + #ifdef _POSIX_OPEN_MAX + nfile = _POSIX_OPEN_MAX; + #else + nfile = 20; /* assume a common value */ + #endif + n = fileno( stderr ); + for(i=0; i < nfile; i++ ) + if( i != n ) + close(i); + errno = 0; + + if( chdir("/") ) + log_fatal("chdir to root failed: %s\n", strerror(errno) ); + umask(0); + + /* do not let possible childs become zombies */ + signal(SIGCHLD, SIG_IGN); + if( opt.verbose ) + log_info("now running as daemon\n"); +} + + +