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;
{
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
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;
}
{
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
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;
}
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) {
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));
{
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);
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;
{
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"));
}
/*
- * 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.
*/
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
* 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 */
#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;
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);
}
/* 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)) {
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);
/* 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);
{
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);
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;
}
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) {