From: Kern Sibbald Date: Thu, 1 May 2003 14:11:00 +0000 (+0000) Subject: First cut ssl framework X-Git-Tag: Release-1.31~180 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=b30de1ea0de78714829a08fce5f31dbd382a903e;p=bacula%2Fbacula First cut ssl framework git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@476 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/console/authenticate.c b/bacula/src/console/authenticate.c index de2b1a0cc9..b378a0976f 100644 --- a/bacula/src/console/authenticate.c +++ b/bacula/src/console/authenticate.c @@ -47,14 +47,15 @@ static char OKhello[] = "1000 OK:"; int authenticate_director(JCR *jcr, DIRRES *director) { BSOCK *dir = jcr->dir_bsock; + int ssl_need = BNET_SSL_NONE; /* * Send my name to the Director then do authentication */ bnet_fsend(dir, hello, "UserAgent"); - if (!cram_md5_get_auth(dir, director->password) || - !cram_md5_auth(dir, director->password)) { + if (!cram_md5_get_auth(dir, director->password, ssl_need) || + !cram_md5_auth(dir, director->password, ssl_need)) { Pmsg0(-1, _("Director authorization problem.\n" "Most likely the passwords do not agree.\n")); return 0; diff --git a/bacula/src/dird/authenticate.c b/bacula/src/dird/authenticate.c index a794b06b0f..81c638c97c 100644 --- a/bacula/src/dird/authenticate.c +++ b/bacula/src/dird/authenticate.c @@ -56,6 +56,7 @@ int authenticate_storage_daemon(JCR *jcr) { BSOCK *sd = jcr->store_bsock; char dirname[MAX_NAME_LENGTH]; + int ssl_need = BNET_SSL_NONE; /* * Send my name to the Storage daemon then do authentication @@ -66,8 +67,8 @@ int authenticate_storage_daemon(JCR *jcr) Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd)); return 0; } - if (!cram_md5_get_auth(sd, jcr->store->password) || - !cram_md5_auth(sd, jcr->store->password)) { + if (!cram_md5_get_auth(sd, jcr->store->password, ssl_need) || + !cram_md5_auth(sd, jcr->store->password, ssl_need)) { Jmsg0(jcr, M_FATAL, 0, _("Director and Storage daemon passwords not the same.\n")); return 0; } @@ -92,6 +93,7 @@ int authenticate_file_daemon(JCR *jcr) { BSOCK *fd = jcr->file_bsock; char dirname[MAX_NAME_LENGTH]; + int ssl_need = BNET_SSL_NONE; /* * Send my name to the File daemon then do authentication @@ -102,8 +104,8 @@ int authenticate_file_daemon(JCR *jcr) Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon. ERR=%s\n"), bnet_strerror(fd)); return 0; } - if (!cram_md5_get_auth(fd, jcr->client->password) || - !cram_md5_auth(fd, jcr->client->password)) { + if (!cram_md5_get_auth(fd, jcr->client->password, ssl_need) || + !cram_md5_auth(fd, jcr->client->password, ssl_need)) { Jmsg(jcr, M_FATAL, 0, _("Director and File daemon passwords not the same.\n")); return 0; } @@ -127,6 +129,7 @@ int authenticate_file_daemon(JCR *jcr) int authenticate_user_agent(BSOCK *ua) { char name[MAXSTRING]; + int ssl_need = BNET_SSL_NONE; int ok; if (ua->msglen < 16 || ua->msglen >= MAXSTRING-1) { @@ -142,8 +145,8 @@ int authenticate_user_agent(BSOCK *ua) return 0; } - ok = cram_md5_auth(ua, director->password) && - cram_md5_get_auth(ua, director->password); + ok = cram_md5_auth(ua, director->password, ssl_need) && + cram_md5_get_auth(ua, director->password, ssl_need); if (!ok) { bnet_fsend(ua, "%s", _(Dir_sorry)); diff --git a/bacula/src/filed/authenticate.c b/bacula/src/filed/authenticate.c index 6d60323d58..ac4867c134 100644 --- a/bacula/src/filed/authenticate.c +++ b/bacula/src/filed/authenticate.c @@ -40,6 +40,7 @@ static int authenticate(int rcode, BSOCK *bs) { POOLMEM *dirname; DIRRES *director; + int ssl_need = BNET_SSL_NONE; if (rcode != R_DIRECTOR) { Emsg1(M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode); @@ -74,8 +75,8 @@ static int authenticate(int rcode, BSOCK *bs) free_pool_memory(dirname); return 0; } - if (!cram_md5_auth(bs, director->password) || - !cram_md5_get_auth(bs, director->password)) { + if (!cram_md5_auth(bs, director->password, ssl_need) || + !cram_md5_get_auth(bs, director->password, ssl_need)) { Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"), bs->who); director = NULL; @@ -113,9 +114,10 @@ int authenticate_storagedaemon(JCR *jcr) { BSOCK *sd = jcr->store_bsock; int stat; + int ssl_need = BNET_SSL_NONE; - stat = cram_md5_get_auth(sd, jcr->sd_auth_key) && - cram_md5_auth(sd, jcr->sd_auth_key); + stat = cram_md5_get_auth(sd, jcr->sd_auth_key, ssl_need) && + cram_md5_auth(sd, jcr->sd_auth_key, ssl_need); memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key)); if (!stat) { Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n")); diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 18e1e13010..ca6bc75dd1 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -349,16 +349,30 @@ bnet_send(BSOCK *bsock) } /* - * Establish an SSL connection. - * If listen is set, the other end initiates the request. - * If listen is not set, I initiate it. + * Establish an SSL connection -- server side + * Codes that ssl_need and ssl_has can take + * BNET_SSL_NONE I cannot do ssl + * BNET_SSL_OK I can do ssl, but it is not required on my end + * BNET_SSL_REQUIRED ssl is required on my end */ int -bnet_ssl(BSOCK *bsock, char *password, int listen) +bnet_ssl_server(BSOCK *bsock, char *password, int ssl_need, int ssl_has) { + /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */ + /* The other side expects a response from us */ return 1; } +/* + * Establish an SSL connection -- client side + */ +int bnet_ssl_client(BSOCK *bsock, char *password, int ssl_need) +{ + /* We are the client so we must wait for the server to notify us */ + return 1; +} + + /* * Wait for a specified time for data to appear on * the BSOCK connection. diff --git a/bacula/src/lib/bsock.h b/bacula/src/lib/bsock.h index 5e0806da0c..1219921d6d 100644 --- a/bacula/src/lib/bsock.h +++ b/bacula/src/lib/bsock.h @@ -32,64 +32,69 @@ */ typedef struct s_bsock { - uint64_t read_seqno; /* read sequence number */ - uint32_t in_msg_no; /* intput message number */ - uint32_t out_msg_no; /* output message number */ - int fd; /* socket file descriptor */ - int32_t msglen; /* message length */ - int port; /* desired port */ - int errors; /* set if errors on socket */ - int suppress_error_msgs; /* set to suppress error messages */ - int b_errno; /* bsock errno */ - time_t timer_start; /* time started read/write */ - int timed_out; /* timed out in read/write */ - int timeout; /* time out after this value */ - int terminated; /* set when BNET_TERMINATE arrives */ - int duped; /* set if duped BSOCK */ - POOLMEM *msg; /* message pool buffer */ - char *who; /* Name of daemon to which we are talking */ - char *host; /* Host name/IP */ - POOLMEM *errmsg; /* edited error message (to be implemented) */ - RES *res; /* Resource to which we are connected */ - struct s_bsock *next; /* next BSOCK if duped */ - int spool; /* set for spooling */ - FILE *spool_fd; /* spooling file */ - void *jcr; /* jcr or NULL for error msgs */ + uint64_t read_seqno; /* read sequence number */ + uint32_t in_msg_no; /* intput message number */ + uint32_t out_msg_no; /* output message number */ + int fd; /* socket file descriptor */ + int32_t msglen; /* message length */ + int port; /* desired port */ + int errors; /* set if errors on socket */ + int suppress_error_msgs; /* set to suppress error messages */ + int b_errno; /* bsock errno */ + time_t timer_start; /* time started read/write */ + int timed_out; /* timed out in read/write */ + int timeout; /* time out after this value */ + int terminated; /* set when BNET_TERMINATE arrives */ + int duped; /* set if duped BSOCK */ + POOLMEM *msg; /* message pool buffer */ + char *who; /* Name of daemon to which we are talking */ + char *host; /* Host name/IP */ + POOLMEM *errmsg; /* edited error message (to be implemented) */ + RES *res; /* Resource to which we are connected */ + struct s_bsock *next; /* next BSOCK if duped */ + int spool; /* set for spooling */ + FILE *spool_fd; /* spooling file */ + void *jcr; /* jcr or NULL for error msgs */ } BSOCK; /* Signal definitions for use in bnet_sig() */ -#define BNET_EOD -1 /* End of data stream, new data may follow */ -#define BNET_EOD_POLL -2 /* End of data and poll all in one */ -#define BNET_STATUS -3 /* Send full status */ -#define BNET_TERMINATE -4 /* Conversation terminated, doing close() */ +#define BNET_EOD -1 /* End of data stream, new data may follow */ +#define BNET_EOD_POLL -2 /* End of data and poll all in one */ +#define BNET_STATUS -3 /* Send full status */ +#define BNET_TERMINATE -4 /* Conversation terminated, doing close() */ #define BNET_POLL -5 /* Poll request, I'm hanging on a read */ -#define BNET_HEARTBEAT -6 /* Heartbeat Response requested */ -#define BNET_HB_RESPONSE -7 /* Only response permited to HB */ -#define BNET_PROMPT -8 /* Prompt for UA */ +#define BNET_HEARTBEAT -6 /* Heartbeat Response requested */ +#define BNET_HB_RESPONSE -7 /* Only response permited to HB */ +#define BNET_PROMPT -8 /* Prompt for UA */ -#define BNET_SETBUF_READ 1 /* Arg for bnet_set_buffer_size */ -#define BNET_SETBUF_WRITE 2 /* Arg for bnet_set_buffer_size */ +#define BNET_SETBUF_READ 1 /* Arg for bnet_set_buffer_size */ +#define BNET_SETBUF_WRITE 2 /* Arg for bnet_set_buffer_size */ /* Return status from bnet_recv() */ #define BNET_SIGNAL -1 #define BNET_HARDEOF -2 #define BNET_ERROR -3 +/* SSL enabling values */ +#define BNET_SSL_NONE 0 /* cannot do SSL */ +#define BNET_SSL_OK 1 /* can do, but not required on my end */ +#define BNET_SSL_REQUIRED 2 /* SSL is required */ + /* * This is the structure of the in memory BPKT */ typedef struct s_bpkt { - char *id; /* String identifier or name of field */ - uint8_t type; /* field type */ - uint32_t len; /* field length for string, name, bytes */ - void *value; /* pointer to value */ + char *id; /* String identifier or name of field */ + uint8_t type; /* field type */ + uint32_t len; /* field length for string, name, bytes */ + void *value; /* pointer to value */ } BPKT; /* * These are the data types that can be sent. * For all values other than string, the storage space * is assumed to be allocated in the receiving packet. - * For BP_STRING if the *value is non-zero, it is a + * For BP_STRING if the *value is non-zero, it is a * pointer to a POOLMEM buffer, and the Memory Pool * routines will be used to assure that the length is * adequate. NOTE!!! This pointer will be changed @@ -97,13 +102,13 @@ typedef struct s_bpkt { * does). If the pointer is NULL, a POOLMEM * buffer will be allocated. */ -#define BP_EOF 0 /* end of file */ -#define BP_CHAR 1 /* Character */ -#define BP_INT32 1 /* 32 bit integer */ -#define BP_UINT32 3 /* Unsigned 32 bit integer */ -#define BP_INT64 4 /* 64 bit integer */ -#define BP_STRING 5 /* string */ -#define BP_NAME 6 /* Name string -- limited length */ -#define BP_BYTES 7 /* Binary bytes */ -#define BP_FLOAT32 8 /* 32 bit floating point */ -#define BP_FLOAT64 9 /* 64 bit floating point */ +#define BP_EOF 0 /* end of file */ +#define BP_CHAR 1 /* Character */ +#define BP_INT32 1 /* 32 bit integer */ +#define BP_UINT32 3 /* Unsigned 32 bit integer */ +#define BP_INT64 4 /* 64 bit integer */ +#define BP_STRING 5 /* string */ +#define BP_NAME 6 /* Name string -- limited length */ +#define BP_BYTES 7 /* Binary bytes */ +#define BP_FLOAT32 8 /* 32 bit floating point */ +#define BP_FLOAT64 9 /* 64 bit floating point */ diff --git a/bacula/src/lib/cram-md5.c b/bacula/src/lib/cram-md5.c index 200d775950..514c190755 100644 --- a/bacula/src/lib/cram-md5.c +++ b/bacula/src/lib/cram-md5.c @@ -30,7 +30,7 @@ #include "bacula.h" /* Authorize other end */ -int cram_md5_auth(BSOCK *bs, char *password) +int cram_md5_auth(BSOCK *bs, char *password, int ssl_need) { struct timeval t1; struct timeval t2; @@ -49,9 +49,14 @@ int cram_md5_auth(BSOCK *bs, char *password) bstrncpy(host, my_name, sizeof(host)); } bsnprintf(chal, sizeof(chal), "<%u.%u@%s>", (uint32_t)random(), (uint32_t)time(NULL), host); - if (!bnet_fsend(bs, "auth cram-md5 %s\n", chal)) { + if (!bnet_fsend(bs, "auth cram-md5 %s ssl=%d\n", chal, ssl_need)) { return 0; } + + if (!bnet_ssl_client(bs, password, ssl_need)) { + return 0; + } + Dmsg1(99, "%s", bs->msg); if (bnet_wait_data(bs, 180) <= 0 || bnet_recv(bs) <= 0) { bmicrosleep(5, 0); @@ -72,20 +77,32 @@ int cram_md5_auth(BSOCK *bs, char *password) } /* Get authorization from other end */ -int cram_md5_get_auth(BSOCK *bs, char *password) +int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need) { char chal[MAXSTRING]; uint8_t hmac[20]; + int ssl_has; /* This is what the other end has */ if (bnet_recv(bs) <= 0) { bmicrosleep(5, 0); return 0; } - if (bs->msglen >= MAXSTRING || sscanf(bs->msg, "auth cram-md5 %s\n", chal) != 1) { - Dmsg1(99, "Wanted auth cram... Got: %s", bs->msg); - bmicrosleep(5, 0); - return 0; + if (bs->msglen >= MAXSTRING) { + Dmsg1(99, "Wanted auth cram... Got: %s", bs->msg); + bmicrosleep(5, 0); + return 0; + } + if (sscanf(bs->msg, "auth cram-md5 %s ssl=%d\n", chal, &ssl_has) != 2) { + ssl_has = BNET_SSL_NONE; + if (sscanf(bs->msg, "auth cram-md5 %s\n", chal) != 1) { + bmicrosleep(5, 0); + return 0; + } } + if (!bnet_ssl_server(bs, password, ssl_need, ssl_has)) { + return 0; + } + hmac_md5((uint8_t *)chal, strlen(chal), (uint8_t *)password, strlen(password), hmac); bs->msglen = bin_to_base64(bs->msg, (char *)hmac, 16) + 1; if (!bnet_send(bs)) { diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index 966047e59c..aad26b6f87 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -53,7 +53,8 @@ int bnet_send (BSOCK *bsock); int bnet_fsend (BSOCK *bs, char *fmt, ...); int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw); int bnet_sig (BSOCK *bs, int sig); -int bnet_ssl (BSOCK *bsock, char *password, int listen); +int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has); +int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need); BSOCK * bnet_connect (void *jcr, int retry_interval, int max_retry_time, char *name, char *host, char *service, int port, int verbose); @@ -72,8 +73,8 @@ void bnet_suppress_error_messages(BSOCK *bsock, int flag); /* cram-md5.c */ -int cram_md5_get_auth(BSOCK *bs, char *password); -int cram_md5_auth(BSOCK *bs, char *password); +int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need); +int cram_md5_auth(BSOCK *bs, char *password, int ssl_need); void hmac_md5(uint8_t* text, int text_len, uint8_t* key, int key_len, uint8_t *hmac); diff --git a/bacula/src/stored/authenticate.c b/bacula/src/stored/authenticate.c index ec235f0228..5b0ce30e9e 100644 --- a/bacula/src/stored/authenticate.c +++ b/bacula/src/stored/authenticate.c @@ -41,6 +41,7 @@ static int authenticate(int rcode, BSOCK *bs) { POOLMEM *dirname; DIRRES *director = NULL; + int ssl_need = BNET_SSL_NONE; if (rcode != R_DIRECTOR) { Emsg1(M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode); @@ -73,8 +74,8 @@ static int authenticate(int rcode, BSOCK *bs) dirname, bs->who); goto bail_out; } - if (!cram_md5_auth(bs, director->password) || - !cram_md5_get_auth(bs, director->password)) { + if (!cram_md5_auth(bs, director->password, ssl_need) || + !cram_md5_get_auth(bs, director->password, ssl_need)) { Emsg0(M_FATAL, 0, _("Incorrect password given by Director.\n")); goto bail_out; } @@ -114,9 +115,10 @@ int authenticate_director(JCR *jcr) int authenticate_filed(JCR *jcr) { BSOCK *fd = jcr->file_bsock; + int ssl_need = BNET_SSL_NONE; - if (cram_md5_auth(fd, jcr->sd_auth_key) && - cram_md5_get_auth(fd, jcr->sd_auth_key)) { + if (cram_md5_auth(fd, jcr->sd_auth_key, ssl_need) && + cram_md5_get_auth(fd, jcr->sd_auth_key, ssl_need)) { jcr->authenticated = TRUE; } if (!jcr->authenticated) {