=== modified file 'Makefile'
--- Makefile 2008-07-21 15:34:44 +0000
+++ Makefile 2008-07-20 03:51:41 +0000
@@ -1,27 +1,7 @@
-WARN=-O -Wall -Wformat=2 -Winit-self -Wmissing-include-dirs -Wswitch-default -Wswitch-enum -Wunused-parameter -Wstrict-aliasing=2 -Wextra -Wfloat-equal -Wundef -Wshadow -Wunsafe-loop-optimizations -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wstrict-prototypes -Wold-style-definition -Wpacked -Wnested-externs -Wunreachable-code -Winline -Wvolatile-register-var
-DEBUG=-ggdb3
-#COVERAGE=--coverage
-LANGUAGE=-std=gnu99
-
-# Do not change these two
-LDFLAGS=$(COVERAGE)
-CFLAGS=$(WARN) $(COVERAGE) $(DEBUG) $(LANGUAGE)
-
-PROGS=plugbasedclient plugins.d/mandosclient plugins.d/passprompt
-
-objects=$(shell for p in $(PROGS); do echo $${p}.o; done)
-
-all: $(PROGS)
-
-plugbasedclient: plugbasedclient.o
- $(LINK.o) -lgnutls $(COMMON) $^ $(LOADLIBES) $(LDLIBS) -o $@
-
-plugins.d/mandosclient: plugins.d/mandosclient.o
- $(LINK.o) -lgnutls -lavahi-core -lgpgme $(COMMON) $^ $(LOADLIBES) $(LDLIBS) -o $@
-
-plugins.d/passprompt: plugins.d/passprompt.o
- $(LINK.o) $(COMMON) $^ $(LOADLIBES) $(LDLIBS) -o $@
-
-.PHONY : clean
+CFLAGS=-Wall -g -std=gnu99
+LDFLAGS=-lgnutls
+
+all: plugbasedclient
+
clean:
- -rm -f $(PROGS) $(objects) core
+ rm -f plugbasedclient
=== modified file 'TODO'
--- TODO 2008-07-21 19:15:06 +0000
+++ TODO 2008-07-20 06:33:48 +0000
@@ -1,16 +1,9 @@
-[Mandos client]
-configuration for OpenPGP key
+[Client]
+configuration for OpenPGP key and interface
IPv4 support
-[Pluginbasedclient]
-disable certain plugins
-change uid to nobody:nogroup
- other drop privs stuff?
-
[Server]
-config file for:
- TXT record
- GnuTLS priority string
+config file
run-time communication with server
[Mandos-tools/utilities]
=== modified file 'plugbasedclient.c'
--- plugbasedclient.c 2008-07-21 15:34:44 +0000
+++ plugbasedclient.c 2008-07-20 03:51:41 +0000
@@ -1,29 +1,3 @@
-/* -*- coding: utf-8 -*- */
-/*
- * Mandos plugin runner - Run Mandos plugins
- *
- * Copyright © 2007-2008 Teddy Hogeborn and Björn Påhlsson.
- *
- * This program 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.
- *
- * This program 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
- * .
- *
- * Contact the authors at and
- * .
- */
-
-#define _FORTIFY_SOURCE 2
-
#include /* popen, fileno */
#include /* and, or, not */
#include /* DIR, opendir, stat, struct stat, waitpid,
@@ -33,8 +7,7 @@
#include /* stat, struct stat */
#include /* stat, struct stat, chdir */
#include /* EXIT_FAILURE */
-#include /* fd_set, select, FD_ZERO, FD_SET,
- FD_ISSET */
+#include /* fd_set, select, FD_ZERO, FD_SET, FD_ISSET */
#include /* strlen, strcpy, strcat */
#include /* true */
#include /* waitpid, WIFEXITED, WEXITSTATUS */
@@ -46,8 +19,8 @@
pid_t pid;
int fd;
char *buffer;
- size_t buffer_size;
- size_t buffer_length;
+ int buffer_size;
+ int buffer_length;
struct process *next;
} process;
@@ -107,8 +80,7 @@
close(pipefd[0]); /* close unused read end of pipe */
dup2(pipefd[1], STDOUT_FILENO); /* replace our stdout */
/* create a new modified argument list */
- char **new_argv = malloc(sizeof(char *)
- * ((unsigned int) argc + 1));
+ char **new_argv = malloc(sizeof(char *) * (argc + 1));
new_argv[0] = filename;
for(int i = 1; i < argc; i++){
new_argv[i] = argv[i];
@@ -159,7 +131,7 @@
> process_itr->buffer_size){
process_itr->buffer = realloc(process_itr->buffer,
process_itr->buffer_size
- + (size_t) BUFFER_SIZE);
+ + BUFFER_SIZE);
if (process_itr->buffer == NULL){
perror(argv[0]);
goto end;
@@ -168,11 +140,7 @@
}
ret = read(process_itr->fd, process_itr->buffer
+ process_itr->buffer_length, BUFFER_SIZE);
- if(ret < 0){
- /* Read error from this process; ignore it */
- continue;
- }
- process_itr->buffer_length += (size_t) ret;
+ process_itr->buffer_length+=ret;
if(ret == 0){
/* got EOF */
/* wait for process exit */
=== added file 'plugins.d/Makefile'
--- plugins.d/Makefile 1970-01-01 00:00:00 +0000
+++ plugins.d/Makefile 2008-07-20 02:52:20 +0000
@@ -0,0 +1,18 @@
+CFLAGS=-Wall -g --std=gnu99
+LDFLAGS=-lgnutls -lavahi-core -lgpgme
+
+PROGS=mandosclient passprompt
+
+objects=mandosclient.o passprompt.o
+
+all: $(PROGS)
+
+mandosclient: mandosclient.o
+ $(LINK.o) -lgnutls -lavahi-core -lgpgme $(COMMON) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
+passprompt: passprompt.o
+ $(LINK.o) $(COMMON) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
+.PHONY : clean
+clean :
+ -rm -f $(PROGS) $(objects) core
=== modified file 'plugins.d/mandosclient.c'
--- plugins.d/mandosclient.c 2008-07-21 22:51:46 +0000
+++ plugins.d/mandosclient.c 2008-07-20 02:52:20 +0000
@@ -1,35 +1,34 @@
-/* -*- coding: utf-8 -*- */
-/*
- * Mandos client - get and decrypt data from a Mandos server
+/* $Id$ */
+
+/* PLEASE NOTE *
+ * This file demonstrates how to use Avahi's core API, this is
+ * the embeddable mDNS stack for embedded applications.
*
- * This program is partly derived from an example program for an Avahi
- * service browser, downloaded from
- * . This
- * includes the following functions: "resolve_callback",
- * "browse_callback", and parts of "main".
- *
- * Everything else is Copyright © 2007-2008 Teddy Hogeborn and Björn
- * Påhlsson.
- *
- * This program 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.
- *
- * This program 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
- * .
- *
- * Contact the authors at and
- * .
+ * End user applications should *not* use this API and should use
+ * the D-Bus or C APIs, please see
+ * client-browse-services.c and glib-integration.c
+ *
+ * I repeat, you probably do *not* want to use this example.
*/
-#define _FORTIFY_SOURCE 2
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi 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 Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
@@ -48,11 +47,10 @@
#include
//mandos client part
-#include /* socket(), inet_pton() */
-#include /* socket(), struct sockaddr_in6,
- struct in6_addr, inet_pton() */
-#include /* All GnuTLS stuff */
-#include /* GnuTLS with openpgp stuff */
+#include /* socket(), setsockopt(), inet_pton() */
+#include /* socket(), setsockopt(), struct sockaddr_in6, struct in6_addr, inet_pton() */
+#include /* ALL GNUTLS STUFF */
+#include /* gnutls with openpgp stuff */
#include /* close() */
#include
@@ -65,8 +63,6 @@
#include /* perror() */
#include
-// getopt long
-#include
#ifndef CERT_ROOT
#define CERT_ROOT "/conf/conf.d/cryptkeyreq/"
@@ -76,8 +72,6 @@
#define BUFFER_SIZE 256
#define DH_BITS 1024
-bool debug = false;
-
typedef struct {
gnutls_session_t session;
gnutls_certificate_credentials_t cred;
@@ -85,20 +79,15 @@
} encrypted_session;
-ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
- char **new_packet, const char *homedir){
+ssize_t gpg_packet_decrypt (char *packet, size_t packet_size, char **new_packet, char *homedir){
gpgme_data_t dh_crypto, dh_plain;
gpgme_ctx_t ctx;
gpgme_error_t rc;
ssize_t ret;
- ssize_t new_packet_capacity = 0;
- ssize_t new_packet_length = 0;
+ size_t new_packet_capacity = 0;
+ size_t new_packet_length = 0;
gpgme_engine_info_t engine_info;
- if (debug){
- fprintf(stderr, "Trying to decrypt OpenPGP packet\n");
- }
-
/* Init GPGME */
gpgme_check_version(NULL);
gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
@@ -147,60 +136,44 @@
return -1;
}
- /* Decrypt data from the FILE pointer to the plaintext data
- buffer */
+ /* Decrypt data from the FILE pointer to the plaintext data buffer */
rc = gpgme_op_decrypt(ctx, dh_crypto, dh_plain);
if (rc != GPG_ERR_NO_ERROR){
fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
gpgme_strsource(rc), gpgme_strerror(rc));
return -1;
}
-
- if(debug){
- fprintf(stderr, "Decryption of OpenPGP packet succeeded\n");
- }
-
- if (debug){
- gpgme_decrypt_result_t result;
- result = gpgme_op_decrypt_result(ctx);
- if (result == NULL){
- fprintf(stderr, "gpgme_op_decrypt_result failed\n");
- } else {
- fprintf(stderr, "Unsupported algorithm: %s\n",
- result->unsupported_algorithm);
- fprintf(stderr, "Wrong key usage: %d\n",
- result->wrong_key_usage);
- if(result->file_name != NULL){
- fprintf(stderr, "File name: %s\n", result->file_name);
- }
- gpgme_recipient_t recipient;
- recipient = result->recipients;
- if(recipient){
- while(recipient != NULL){
- fprintf(stderr, "Public key algorithm: %s\n",
- gpgme_pubkey_algo_name(recipient->pubkey_algo));
- fprintf(stderr, "Key ID: %s\n", recipient->keyid);
- fprintf(stderr, "Secret key available: %s\n",
- recipient->status == GPG_ERR_NO_SECKEY
- ? "No" : "Yes");
- recipient = recipient->next;
- }
- }
- }
- }
+/* gpgme_decrypt_result_t result; */
+/* result = gpgme_op_decrypt_result(ctx); */
+/* fprintf(stderr, "Unsupported algorithm: %s\n", result->unsupported_algorithm); */
+/* fprintf(stderr, "Wrong key usage: %d\n", result->wrong_key_usage); */
+/* if(result->file_name != NULL){ */
+/* fprintf(stderr, "File name: %s\n", result->file_name); */
+/* } */
+/* gpgme_recipient_t recipient; */
+/* recipient = result->recipients; */
+/* if(recipient){ */
+/* while(recipient != NULL){ */
+/* fprintf(stderr, "Public key algorithm: %s\n", */
+/* gpgme_pubkey_algo_name(recipient->pubkey_algo)); */
+/* fprintf(stderr, "Key ID: %s\n", recipient->keyid); */
+/* fprintf(stderr, "Secret key available: %s\n", */
+/* recipient->status == GPG_ERR_NO_SECKEY ? "No" : "Yes"); */
+/* recipient = recipient->next; */
+/* } */
+/* } */
+
/* Delete the GPGME FILE pointer cryptotext data buffer */
gpgme_data_release(dh_crypto);
/* Seek back to the beginning of the GPGME plaintext data buffer */
- gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET);
+ gpgme_data_seek(dh_plain, 0, SEEK_SET);
*new_packet = 0;
while(true){
if (new_packet_length + BUFFER_SIZE > new_packet_capacity){
- *new_packet = realloc(*new_packet,
- (unsigned int)new_packet_capacity
- + BUFFER_SIZE);
+ *new_packet = realloc(*new_packet, new_packet_capacity + BUFFER_SIZE);
if (*new_packet == NULL){
perror("realloc");
return -1;
@@ -208,10 +181,10 @@
new_packet_capacity += BUFFER_SIZE;
}
- ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length,
- BUFFER_SIZE);
+ ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length, BUFFER_SIZE);
/* Print the data, if any */
if (ret == 0){
+ /* If password is empty, then a incorrect error will be printed */
break;
}
if(ret < 0){
@@ -221,15 +194,7 @@
new_packet_length += ret;
}
- /* FIXME: check characters before printing to screen so to not print
- terminal control characters */
- /* if(debug){ */
- /* fprintf(stderr, "decrypted password is: "); */
- /* fwrite(*new_packet, 1, new_packet_length, stderr); */
- /* fprintf(stderr, "\n"); */
- /* } */
-
- /* Delete the GPGME plaintext data buffer */
+ /* Delete the GPGME plaintext data buffer */
gpgme_data_release(dh_plain);
return new_packet_length;
}
@@ -241,8 +206,7 @@
return ret;
}
-void debuggnutls(__attribute__((unused)) int level,
- const char* string){
+void debuggnutls(int level, const char* string){
fprintf(stderr, "%s", string);
}
@@ -250,79 +214,67 @@
const char *err;
int ret;
- if(debug){
- fprintf(stderr, "Initializing GnuTLS\n");
- }
-
if ((ret = gnutls_global_init ())
!= GNUTLS_E_SUCCESS) {
fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
return -1;
}
- if (debug){
- gnutls_global_set_log_level(11);
- gnutls_global_set_log_function(debuggnutls);
- }
-
+ /* Uncomment to enable full debuggin on the gnutls library */
+ /* gnutls_global_set_log_level(11); */
+ /* gnutls_global_set_log_function(debuggnutls); */
+
+
/* openpgp credentials */
if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
!= GNUTLS_E_SUCCESS) {
- fprintf (stderr, "memory error: %s\n",
- safer_gnutls_strerror(ret));
+ fprintf (stderr, "memory error: %s\n", safer_gnutls_strerror(ret));
return -1;
}
-
- if(debug){
- fprintf(stderr, "Attempting to use OpenPGP certificate %s"
- " and keyfile %s as GnuTLS credentials\n", CERTFILE,
- KEYFILE);
- }
-
+
ret = gnutls_certificate_set_openpgp_key_file
(es->cred, CERTFILE, KEYFILE, GNUTLS_OPENPGP_FMT_BASE64);
if (ret != GNUTLS_E_SUCCESS) {
fprintf
- (stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
- " '%s')\n",
+ (stderr, "Error[%d] while reading the OpenPGP key pair ('%s', '%s')\n",
ret, CERTFILE, KEYFILE);
fprintf(stdout, "The Error is: %s\n",
safer_gnutls_strerror(ret));
return -1;
}
-
- //GnuTLS server initialization
+
+ //Gnutls server initialization
if ((ret = gnutls_dh_params_init (&es->dh_params))
!= GNUTLS_E_SUCCESS) {
fprintf (stderr, "Error in dh parameter initialization: %s\n",
safer_gnutls_strerror(ret));
return -1;
}
-
+
if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
!= GNUTLS_E_SUCCESS) {
fprintf (stderr, "Error in prime generation: %s\n",
safer_gnutls_strerror(ret));
return -1;
}
-
+
gnutls_certificate_set_dh_params (es->cred, es->dh_params);
-
- // GnuTLS session creation
+
+ // Gnutls session creation
if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
!= GNUTLS_E_SUCCESS){
- fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
+ fprintf(stderr, "Error in gnutls session initialization: %s\n",
safer_gnutls_strerror(ret));
}
-
+
if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
!= GNUTLS_E_SUCCESS) {
fprintf(stderr, "Syntax error at: %s\n", err);
- fprintf(stderr, "GnuTLS error: %s\n",
+ fprintf(stderr, "Gnutls error: %s\n",
safer_gnutls_strerror(ret));
return -1;
}
-
+
if ((ret = gnutls_credentials_set
(es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
!= GNUTLS_E_SUCCESS) {
@@ -330,36 +282,29 @@
safer_gnutls_strerror(ret));
return -1;
}
-
+
/* ignore client certificate if any. */
- gnutls_certificate_server_set_request (es->session,
- GNUTLS_CERT_IGNORE);
+ gnutls_certificate_server_set_request (es->session, GNUTLS_CERT_IGNORE);
gnutls_dh_set_prime_bits (es->session, DH_BITS);
return 0;
}
-void empty_log(__attribute__((unused)) AvahiLogLevel level,
- __attribute__((unused)) const char *txt){}
+void empty_log(AvahiLogLevel level, const char *txt){}
-int start_mandos_communication(const char *ip, uint16_t port,
- unsigned int if_index){
+int start_mandos_communcation(char *ip, uint16_t port){
int ret, tcp_sd;
struct sockaddr_in6 to;
+ struct in6_addr ip_addr;
encrypted_session es;
char *buffer = NULL;
char *decrypted_buffer;
size_t buffer_length = 0;
size_t buffer_capacity = 0;
ssize_t decrypted_buffer_size;
- size_t written = 0;
int retval = 0;
- char interface[IF_NAMESIZE];
-
- if(debug){
- fprintf(stderr, "Setting up a tcp connection to %s\n", ip);
- }
+
tcp_sd = socket(PF_INET6, SOCK_STREAM, 0);
if(tcp_sd < 0) {
@@ -367,20 +312,15 @@
return -1;
}
- if(if_indextoname(if_index, interface) == NULL){
- if(debug){
- perror("if_indextoname");
- }
+ ret = setsockopt(tcp_sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
+ if(tcp_sd < 0) {
+ perror("setsockopt bindtodevice");
return -1;
}
- if(debug){
- fprintf(stderr, "Binding to interface %s\n", interface);
- }
-
- memset(&to,0,sizeof(to)); /* Spurious warning */
+ memset(&to,0,sizeof(to));
to.sin6_family = AF_INET6;
- ret = inet_pton(AF_INET6, ip, &to.sin6_addr);
+ ret = inet_pton(AF_INET6, ip, &ip_addr);
if (ret < 0 ){
perror("inet_pton");
return -1;
@@ -389,13 +329,8 @@
fprintf(stderr, "Bad address: %s\n", ip);
return -1;
}
- to.sin6_port = htons(port); /* Spurious warning */
-
- to.sin6_scope_id = (uint32_t)if_index;
-
- if(debug){
- fprintf(stderr, "Connection to: %s\n", ip);
- }
+ to.sin6_port = htons(port);
+ to.sin6_scope_id = if_nametoindex("eth0");
ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
if (ret < 0){
@@ -408,14 +343,10 @@
retval = -1;
return -1;
}
-
- gnutls_transport_set_ptr (es.session,
- (gnutls_transport_ptr_t) tcp_sd);
-
- if(debug){
- fprintf(stderr, "Establishing TLS session with %s\n", ip);
- }
-
+
+
+ gnutls_transport_set_ptr (es.session, (gnutls_transport_ptr_t) tcp_sd);
+
ret = gnutls_handshake (es.session);
if (ret != GNUTLS_E_SUCCESS){
@@ -424,14 +355,8 @@
retval = -1;
goto exit;
}
-
- //Retrieve OpenPGP packet that contains the wanted password
-
- if(debug){
- fprintf(stderr, "Retrieving pgp encrypted password from %s\n",
- ip);
- }
+ //retrive password
while(true){
if (buffer_length + BUFFER_SIZE > buffer_capacity){
buffer = realloc(buffer, buffer_capacity + BUFFER_SIZE);
@@ -462,50 +387,28 @@
}
break;
default:
- fprintf(stderr, "Unknown error while reading data from"
- " encrypted session with mandos server\n");
+ fprintf(stderr, "Unknown error while reading data from encrypted session with mandos server\n");
retval = -1;
gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
goto exit;
}
} else {
- buffer_length += (size_t) ret;
+ buffer_length += ret;
}
}
-
+
if (buffer_length > 0){
- decrypted_buffer_size = pgp_packet_decrypt(buffer,
- buffer_length,
- &decrypted_buffer,
- CERT_ROOT);
- if (decrypted_buffer_size >= 0){
- while(written < decrypted_buffer_size){
- ret = (int)fwrite (decrypted_buffer + written, 1,
- (size_t)decrypted_buffer_size - written,
- stdout);
- if(ret == 0 and ferror(stdout)){
- if(debug){
- fprintf(stderr, "Error writing encrypted data: %s\n",
- strerror(errno));
- }
- retval = -1;
- break;
- }
- written += (size_t)ret;
- }
+ if ((decrypted_buffer_size = gpg_packet_decrypt(buffer, buffer_length, &decrypted_buffer, CERT_ROOT)) == 0){
+ retval = -1;
+ } else {
+ fwrite (decrypted_buffer, 1, decrypted_buffer_size, stdout);
free(decrypted_buffer);
- } else {
- retval = -1;
}
}
+ free(buffer);
+
//shutdown procedure
-
- if(debug){
- fprintf(stderr, "Closing TLS session\n");
- }
-
- free(buffer);
gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
exit:
close(tcp_sd);
@@ -520,7 +423,7 @@
static void resolve_callback(
AvahiSServiceResolver *r,
- AvahiIfIndex interface,
+ AVAHI_GCC_UNUSED AvahiIfIndex interface,
AVAHI_GCC_UNUSED AvahiProtocol protocol,
AvahiResolverEvent event,
const char *name,
@@ -529,41 +432,31 @@
const char *host_name,
const AvahiAddress *address,
uint16_t port,
- AVAHI_GCC_UNUSED AvahiStringList *txt,
- AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ AvahiStringList *txt,
+ AvahiLookupResultFlags flags,
AVAHI_GCC_UNUSED void* userdata) {
- assert(r); /* Spurious warning */
-
- /* Called whenever a service has been resolved successfully or
- timed out */
-
- switch (event) {
- default:
- case AVAHI_RESOLVER_FAILURE:
- fprintf(stderr, "(Resolver) Failed to resolve service '%s' of"
- " type '%s' in domain '%s': %s\n", name, type, domain,
- avahi_strerror(avahi_server_errno(server)));
- break;
-
- case AVAHI_RESOLVER_FOUND:
- {
- char ip[AVAHI_ADDRESS_STR_MAX];
- avahi_address_snprint(ip, sizeof(ip), address);
- if(debug){
- fprintf(stderr, "Mandos server found on %s (%s) on port %d\n",
- host_name, ip, port);
- }
- int ret = start_mandos_communication(ip, port,
- (unsigned int) interface);
- if (ret == 0){
- exit(EXIT_SUCCESS);
- } else {
- exit(EXIT_FAILURE);
- }
+ assert(r);
+
+ /* Called whenever a service has been resolved successfully or timed out */
+
+ switch (event) {
+ case AVAHI_RESOLVER_FAILURE:
+ fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_server_errno(server)));
+ break;
+
+ case AVAHI_RESOLVER_FOUND: {
+ char ip[AVAHI_ADDRESS_STR_MAX];
+ avahi_address_snprint(ip, sizeof(ip), address);
+ int ret = start_mandos_communcation(ip, port);
+ if (ret == 0){
+ exit(EXIT_SUCCESS);
+ } else {
+ exit(EXIT_FAILURE);
+ }
+ }
}
- }
- avahi_s_service_resolver_free(r);
+ avahi_s_service_resolver_free(r);
}
static void browse_callback(
@@ -578,40 +471,35 @@
void* userdata) {
AvahiServer *s = userdata;
- assert(b); /* Spurious warning */
-
- /* Called whenever a new services becomes available on the LAN or
- is removed from the LAN */
-
+ assert(b);
+
+ /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
+
switch (event) {
- default:
- case AVAHI_BROWSER_FAILURE:
-
- fprintf(stderr, "(Browser) %s\n",
- avahi_strerror(avahi_server_errno(server)));
- avahi_simple_poll_quit(simple_poll);
- return;
-
- case AVAHI_BROWSER_NEW:
- /* We ignore the returned resolver object. In the callback
- function we free it. If the server is terminated before
- the callback function is called the server will free
- the resolver for us. */
-
- if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
- type, domain,
- AVAHI_PROTO_INET6, 0,
- resolve_callback, s)))
- fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
- avahi_strerror(avahi_server_errno(s)));
- break;
-
- case AVAHI_BROWSER_REMOVE:
- break;
-
- case AVAHI_BROWSER_ALL_FOR_NOW:
- case AVAHI_BROWSER_CACHE_EXHAUSTED:
- break;
+
+ case AVAHI_BROWSER_FAILURE:
+
+ fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_server_errno(server)));
+ avahi_simple_poll_quit(simple_poll);
+ return;
+
+ case AVAHI_BROWSER_NEW:
+ /* We ignore the returned resolver object. In the callback
+ function we free it. If the server is terminated before
+ the callback function is called the server will free
+ the resolver for us. */
+
+ if (!(avahi_s_service_resolver_new(s, interface, protocol, name, type, domain, AVAHI_PROTO_INET6, 0, resolve_callback, s)))
+ fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_server_errno(s)));
+
+ break;
+
+ case AVAHI_BROWSER_REMOVE:
+ break;
+
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ break;
}
}
@@ -619,47 +507,17 @@
AvahiServerConfig config;
AvahiSServiceBrowser *sb = NULL;
int error;
- int ret;
- int returncode = EXIT_SUCCESS;
- const char *interface = "eth0";
-
- while (true){
- static struct option long_options[] = {
- {"debug", no_argument, (int *)&debug, 1},
- {"interface", required_argument, 0, 'i'},
- {0, 0, 0, 0} };
-
- int option_index = 0;
- ret = getopt_long (argc, argv, "i:", long_options,
- &option_index);
-
- if (ret == -1){
- break;
- }
-
- switch(ret){
- case 0:
- break;
- case 'i':
- interface = optarg;
- break;
- default:
- exit(EXIT_FAILURE);
- }
- }
-
- if (not debug){
- avahi_set_log_function(empty_log);
- }
+ int ret = 1;
+
+ avahi_set_log_function(empty_log);
/* Initialize the psuedo-RNG */
- srand((unsigned int) time(NULL));
+ srand(time(NULL));
/* Allocate main loop object */
if (!(simple_poll = avahi_simple_poll_new())) {
fprintf(stderr, "Failed to create simple poll object.\n");
-
- goto exit;
+ goto fail;
}
/* Do not publish any local records */
@@ -669,48 +527,35 @@
config.publish_workstation = 0;
config.publish_domain = 0;
+/* /\* Set a unicast DNS server for wide area DNS-SD *\/ */
+/* avahi_address_parse("193.11.177.11", AVAHI_PROTO_UNSPEC, &config.wide_area_servers[0]); */
+/* config.n_wide_area_servers = 1; */
+/* config.enable_wide_area = 1; */
+
/* Allocate a new server */
- server = avahi_server_new(avahi_simple_poll_get(simple_poll),
- &config, NULL, NULL, &error);
+ server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, NULL, NULL, &error);
/* Free the configuration data */
avahi_server_config_free(&config);
- /* Check if creating the server object succeeded */
+ /* Check wether creating the server object succeeded */
if (!server) {
- fprintf(stderr, "Failed to create server: %s\n",
- avahi_strerror(error));
- returncode = EXIT_FAILURE;
- goto exit;
+ fprintf(stderr, "Failed to create server: %s\n", avahi_strerror(error));
+ goto fail;
}
/* Create the service browser */
- sb = avahi_s_service_browser_new(server,
- (AvahiIfIndex)
- if_nametoindex(interface),
- AVAHI_PROTO_INET6,
- "_mandos._tcp", NULL, 0,
- browse_callback, server);
- if (!sb) {
- fprintf(stderr, "Failed to create service browser: %s\n",
- avahi_strerror(avahi_server_errno(server)));
- returncode = EXIT_FAILURE;
- goto exit;
+ if (!(sb = avahi_s_service_browser_new(server, if_nametoindex("eth0"), AVAHI_PROTO_INET6, "_mandos._tcp", NULL, 0, browse_callback, server))) {
+ fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_server_errno(server)));
+ goto fail;
}
/* Run the main loop */
-
- if (debug){
- fprintf(stderr, "Starting avahi loop search\n");
- }
-
avahi_simple_poll_loop(simple_poll);
- exit:
-
- if (debug){
- fprintf(stderr, "%s exiting\n", argv[0]);
- }
+ ret = 0;
+
+fail:
/* Cleanup things */
if (sb)
@@ -722,5 +567,5 @@
if (simple_poll)
avahi_simple_poll_free(simple_poll);
- return returncode;
+ return ret;
}
=== modified file 'plugins.d/passprompt.c'
--- plugins.d/passprompt.c 2008-07-21 15:34:44 +0000
+++ plugins.d/passprompt.c 2008-07-20 02:52:20 +0000
@@ -1,30 +1,5 @@
-/* -*- coding: utf-8 -*- */
-/*
- * Passprompt - Read a password from the terminal and print it
- *
- * Copyright © 2007-2008 Teddy Hogeborn and Björn Påhlsson.
- *
- * This program 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.
- *
- * This program 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
- * .
- *
- * Contact the authors at and
- * .
- */
-
#define _GNU_SOURCE /* getline() */
#define _FORTIFY_SOURCE 2
-
#include /* struct termios, tcsetattr(),
TCSAFLUSH, tcgetattr(), ECHO */
#include /* struct termios, tcsetattr(),
@@ -36,66 +11,29 @@
SIGQUIT, SIGHUP, SIGTERM */
#include /* NULL, size_t */
#include /* ssize_t */
-#include /* EXIT_SUCCESS, EXIT_FAILURE,
- getopt_long */
+#include /* EXIT_SUCCESS, EXIT_FAILURE */
#include /* fprintf(), stderr, getline(),
stdin, feof(), perror(), fputc(),
- stdout, getopt_long */
+ stdout */
#include /* errno, EINVAL */
#include /* or, not */
#include /* bool, false, true */
-#include /* strlen, rindex, strncmp, strcmp */
-#include /* getopt_long */
volatile bool quit_now = false;
-bool debug = false;
-void termination_handler(__attribute__((unused))int signum){
+void termination_handler(int signum){
quit_now = true;
}
int main(int argc, char **argv){
- ssize_t ret;
+ ssize_t ret = -1;
size_t n;
struct termios t_new, t_old;
char *buffer = NULL;
- char *prefix = NULL;
int status = EXIT_SUCCESS;
struct sigaction old_action,
new_action = { .sa_handler = termination_handler,
.sa_flags = 0 };
-
- while (true){
- static struct option long_options[] = {
- {"debug", no_argument, (int *)&debug, 1},
- {"prefix", required_argument, 0, 'p'},
- {0, 0, 0, 0} };
-
- int option_index = 0;
- ret = getopt_long (argc, argv, "p:", long_options, &option_index);
-
- if (ret == -1){
- break;
- }
-
- switch(ret){
- case 0:
- break;
- case 'p':
- prefix = optarg;
- break;
- default:
- fprintf(stderr, "bad arguments\n");
- exit(EXIT_FAILURE);
- }
- }
-
- if (debug){
- fprintf(stderr, "Starting %s\n", argv[0]);
- }
- if (debug){
- fprintf(stderr, "Storing current terminal attributes\n");
- }
if (tcgetattr(STDIN_FILENO, &t_old) != 0){
return EXIT_FAILURE;
@@ -118,11 +56,6 @@
sigaction(SIGTERM, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGTERM, &new_action, NULL);
-
-
- if (debug){
- fprintf(stderr, "Removing echo flag from terminal attributes\n");
- }
t_new = t_old;
t_new.c_lflag &= ~ECHO;
@@ -130,21 +63,13 @@
perror("tcsetattr-echo");
return EXIT_FAILURE;
}
-
- if (debug){
- fprintf(stderr, "Waiting for input from stdin \n");
- }
+
while(true){
if (quit_now){
status = EXIT_FAILURE;
break;
}
-
- if(prefix){
- fprintf(stderr, "%s Password: ", prefix);
- } else {
- fprintf(stderr, "Password: ");
- }
+ fprintf(stderr, "Password: ");
ret = getline(&buffer, &n, stdin);
if (ret > 0){
fprintf(stdout, "%s", buffer);
@@ -162,16 +87,9 @@
fputc('\n', stderr);
}
- if (debug){
- fprintf(stderr, "Restoring terminal attributes\n");
- }
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_old) != 0){
perror("tcsetattr+echo");
}
-
- if (debug){
- fprintf(stderr, "%s is exiting\n", argv[0]);
- }
return status;
}
=== modified file 'server.py'
--- server.py 2008-07-21 01:50:31 +0000
+++ server.py 2008-07-20 06:33:48 +0000
@@ -1,34 +1,5 @@
#!/usr/bin/python
# -*- mode: python; coding: utf-8 -*-
-#
-# Mandos server - give out binary blobs to connecting clients.
-#
-# This program is partly derived from an example program for an Avahi
-# service publisher, downloaded from
-# . This includes the
-# following functions: "add_service", "remove_service",
-# "server_state_changed", "entry_group_state_changed", and some lines
-# in "main".
-#
-# Everything else is Copyright © 2007-2008 Teddy Hogeborn and Björn
-# Påhlsson.
-#
-# This program 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.
-#
-# This program 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 .
-#
-# Contact the authors at and
-# .
-#
from __future__ import division
@@ -53,8 +24,6 @@
import subprocess
import atexit
import stat
-import logging
-import logging.handlers
import dbus
import gobject
@@ -62,17 +31,8 @@
from dbus.mainloop.glib import DBusGMainLoop
import ctypes
-# Brief description of the operation of this program:
-#
-# This server announces itself as a Zeroconf service. Connecting
-# clients use the TLS protocol, with the unusual quirk that this
-# server program acts as a TLS "client" while the connecting clients
-# acts as a TLS "server". The clients (acting as a TLS "server") must
-# supply an OpenPGP certificate, and the fingerprint of this
-# certificate is used by this server to look up (in a list read from a
-# file at start time) which binary blob to give the client. No other
-# authentication or authorization is done by this server.
-
+import logging
+import logging.handlers
logger = logging.Logger('mandos')
syslogger = logging.handlers.SysLogHandler\
@@ -84,9 +44,9 @@
# This variable is used to optionally bind to a specified interface.
# It is a global variable to fit in with the other variables from the
-# Avahi example code.
+# Avahi server example code.
serviceInterface = avahi.IF_UNSPEC
-# From the Avahi example code:
+# From the Avahi server example code:
serviceName = "Mandos"
serviceType = "_mandos._tcp" # http://www.dns-sd.org/ServiceTypes.html
servicePort = None # Not known at startup
@@ -155,8 +115,6 @@
def __init__(self, name=None, options=None, stop_hook=None,
fingerprint=None, secret=None, secfile=None,
fqdn=None, timeout=None, interval=-1, checker=None):
- """Note: the 'checker' argument sets the 'checker_command'
- attribute and not the 'checker' attribute.."""
self.name = name
# Uppercase and remove spaces from fingerprint
# for later comparison purposes with return value of
@@ -189,7 +147,7 @@
self.checker_callback_tag = None
self.check_command = checker
def start(self):
- """Start this client's checker and timeout hooks"""
+ """Start this clients checker and timeout hooks"""
# Schedule a new checker to be started an 'interval' from now,
# and every interval from then on.
self.checker_initiator_tag = gobject.timeout_add\
@@ -205,18 +163,12 @@
"""Stop this client.
The possibility that this client might be restarted is left
open, but not currently used."""
- # If this client doesn't have a secret, it is already stopped.
- if self.secret:
- logger.debug(u"Stopping client %s", self.name)
- self.secret = None
- else:
- return False
- if hasattr(self, "stop_initiator_tag") \
- and self.stop_initiator_tag:
+ logger.debug(u"Stopping client %s", self.name)
+ self.secret = None
+ if self.stop_initiator_tag:
gobject.source_remove(self.stop_initiator_tag)
self.stop_initiator_tag = None
- if hasattr(self, "checker_initiator_tag") \
- and self.checker_initiator_tag:
+ if self.checker_initiator_tag:
gobject.source_remove(self.checker_initiator_tag)
self.checker_initiator_tag = None
self.stop_checker()
@@ -225,13 +177,19 @@
# Do not run this again if called by a gobject.timeout_add
return False
def __del__(self):
- self.stop_hook = None
- self.stop()
+ # Some code duplication here and in stop()
+ if hasattr(self, "stop_initiator_tag") \
+ and self.stop_initiator_tag:
+ gobject.source_remove(self.stop_initiator_tag)
+ self.stop_initiator_tag = None
+ if hasattr(self, "checker_initiator_tag") \
+ and self.checker_initiator_tag:
+ gobject.source_remove(self.checker_initiator_tag)
+ self.checker_initiator_tag = None
+ self.stop_checker()
def checker_callback(self, pid, condition):
"""The checker has completed, so take appropriate actions."""
now = datetime.datetime.now()
- self.checker_callback_tag = None
- self.checker = None
if os.WIFEXITED(condition) \
and (os.WEXITSTATUS(condition) == 0):
logger.debug(u"Checker for %(name)s succeeded",
@@ -247,18 +205,12 @@
else:
logger.debug(u"Checker for %(name)s failed",
vars(self))
+ self.checker = None
+ self.checker_callback_tag = None
def start_checker(self):
"""Start a new checker subprocess if one is not running.
If a checker already exists, leave it running and do
nothing."""
- # The reason for not killing a running checker is that if we
- # did that, then if a checker (for some reason) started
- # running slowly and taking more than 'interval' time, the
- # client would inevitably timeout, since no checker would get
- # a chance to run to completion. If we instead leave running
- # checkers alone, the checker would have to take more time
- # than 'timeout' for the client to be declared invalid, which
- # is as it should be.
if self.checker is None:
try:
command = self.check_command % self.fqdn
@@ -289,20 +241,13 @@
return True
def stop_checker(self):
"""Force the checker process, if any, to stop."""
- if self.checker_callback_tag:
- gobject.source_remove(self.checker_callback_tag)
- self.checker_callback_tag = None
if not hasattr(self, "checker") or self.checker is None:
return
- logger.debug("Stopping checker for %(name)s", vars(self))
- try:
- os.kill(self.checker.pid, signal.SIGTERM)
- #os.sleep(0.5)
- #if self.checker.poll() is None:
- # os.kill(self.checker.pid, signal.SIGKILL)
- except OSError, error:
- if error.errno != errno.ESRCH:
- raise
+ gobject.source_remove(self.checker_callback_tag)
+ self.checker_callback_tag = None
+ os.kill(self.checker.pid, signal.SIGTERM)
+ if self.checker.poll() is None:
+ os.kill(self.checker.pid, signal.SIGKILL)
self.checker = None
def still_valid(self, now=None):
"""Has the timeout not yet passed for this client?"""
@@ -315,7 +260,7 @@
def peer_certificate(session):
- "Return the peer's OpenPGP certificate as a bytestring"
+ "Return an OpenPGP data packet string for the peer's certificate"
# If not an OpenPGP certificate...
if gnutls.library.functions.gnutls_certificate_type_get\
(session._c_object) \
@@ -332,7 +277,7 @@
def fingerprint(openpgp):
- "Convert an OpenPGP bytestring to a hexdigit fingerprint string"
+ "Convert an OpenPGP data string to a hexdigit fingerprint string"
# New empty GnuTLS certificate
crt = gnutls.library.types.gnutls_openpgp_crt_t()
gnutls.library.functions.gnutls_openpgp_crt_init\
@@ -397,7 +342,7 @@
return
logger.debug(u"Fingerprint: %s", fpr)
client = None
- for c in self.server.clients:
+ for c in clients:
if c.fingerprint == fpr:
client = c
break
@@ -504,7 +449,7 @@
def add_service():
- """Derived from the Avahi example code"""
+ """From the Avahi server example code"""
global group, serviceName, serviceType, servicePort, serviceTXT, \
domain, host
if group is None:
@@ -529,7 +474,7 @@
def remove_service():
- """From the Avahi example code"""
+ """From the Avahi server example code"""
global group
if not group is None:
@@ -537,7 +482,7 @@
def server_state_changed(state):
- """Derived from the Avahi example code"""
+ """From the Avahi server example code"""
if state == avahi.SERVER_COLLISION:
logger.warning(u"Server name collision")
remove_service()
@@ -546,7 +491,7 @@
def entry_group_state_changed(state, error):
- """Derived from the Avahi example code"""
+ """From the Avahi server example code"""
global serviceName, server, rename_count
logger.debug(u"state change: %i", state)
@@ -622,18 +567,13 @@
sys.exit(status)
-def main():
- global exitstatus
+if __name__ == '__main__':
exitstatus = 0
- global main_loop_started
main_loop_started = False
-
parser = OptionParser()
parser.add_option("-i", "--interface", type="string",
default=None, metavar="IF",
help="Bind to interface IF")
- parser.add_option("-a", "--address", type="string", default=None,
- help="Address to listen for requests on")
parser.add_option("-p", "--port", type="int", default=None,
help="Port number to receive requests on")
parser.add_option("--timeout", type="string", # Parsed later
@@ -666,13 +606,10 @@
# Parse config file
defaults = { "checker": "fping -q -- %%(fqdn)s" }
client_config = ConfigParser.SafeConfigParser(defaults)
- #client_config.readfp(open("global.conf"), "global.conf")
+ #client_config.readfp(open("secrets.conf"), "secrets.conf")
client_config.read("mandos-clients.conf")
- global main_loop
- global bus
- global server
- # From the Avahi example code
+ # From the Avahi server example code
DBusGMainLoop(set_as_default=True )
main_loop = gobject.MainLoop()
bus = dbus.SystemBus()
@@ -710,14 +647,13 @@
def cleanup():
"Cleanup function; run on exit"
global group
- # From the Avahi example code
+ # From the Avahi server example code
if not group is None:
group.Free()
group = None
# End of Avahi example code
- while clients:
- client = clients.pop()
+ for client in clients:
client.stop_hook = None
client.stop()
@@ -731,20 +667,18 @@
for client in clients:
client.start()
- tcp_server = IPv6_TCPServer((options.address, options.port),
+ tcp_server = IPv6_TCPServer((None, options.port),
tcp_handler,
options=options,
clients=clients)
# Find out what random port we got
- global servicePort
servicePort = tcp_server.socket.getsockname()[1]
logger.debug(u"Now listening on port %d", servicePort)
if options.interface is not None:
- global serviceInterface
serviceInterface = if_nametoindex(options.interface)
- # From the Avahi example code
+ # From the Avahi server example code
server.connect_to_signal("StateChanged", server_state_changed)
try:
server_state_changed(server.GetState())
@@ -758,7 +692,6 @@
tcp_server.handle_request(*args[2:],
**kwargs) or True)
try:
- logger.debug("Starting main loop")
main_loop_started = True
main_loop.run()
except KeyboardInterrupt:
@@ -766,6 +699,3 @@
print
sys.exit(exitstatus)
-
-if __name__ == '__main__':
- main()