]> git.sur5r.net Git - bacula/bacula/commitdiff
First cut ssl framework
authorKern Sibbald <kern@sibbald.com>
Thu, 1 May 2003 14:11:00 +0000 (14:11 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 1 May 2003 14:11:00 +0000 (14:11 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@476 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/console/authenticate.c
bacula/src/dird/authenticate.c
bacula/src/filed/authenticate.c
bacula/src/lib/bnet.c
bacula/src/lib/bsock.h
bacula/src/lib/cram-md5.c
bacula/src/lib/protos.h
bacula/src/stored/authenticate.c

index de2b1a0cc92ea234fd447978956b50587804d79c..b378a0976f84a6b1f544a8ad0f9dce563568d67a 100644 (file)
@@ -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;
index a794b06b0f1044e217b570f33bb5c57012a40098..81c638c97cc5b1299e5c314cbf4be3d7c788a762 100644 (file)
@@ -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));
index 6d60323d582ac05d76dfe559dd8ac0944abf40ec..ac4867c1341476749567feafd4b3007ec07b965a 100644 (file)
@@ -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"));
index 18e1e13010c3c6e31bd31549cda9d3de2cb7c80e..ca6bc75dd1b48aecfa21f661e9eb4f41a74b62f9 100644 (file)
@@ -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.
index 5e0806da0cfd45e845b594852188dec45d1e4168..1219921d6d87e5f69134f180a3c2edcb2def319a 100644 (file)
  */
 
 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 */
index 200d7759507ee5b0c8669dd26521291915f7884a..514c190755e55ee8ac0b51741dfdd11a9f4386f2 100644 (file)
@@ -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)) {
index 966047e59c1fd3019510d30270c59f087d31cd02..aad26b6f87cccfded352d45a3cdb2798423e0bbd 100644 (file)
@@ -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);
 
index ec235f0228e7f3ced2391fcf5dd1142b2dbb426a..5b0ce30e9eac0a0c098eedb1258c792b80a78c40 100644 (file)
@@ -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) {