[DRBD-cvs] r1728 - in trunk: drbd drbd/linux scripts

svn at svn.drbd.org svn at svn.drbd.org
Thu Jan 20 14:26:07 CET 2005


Author: phil
Date: 2005-01-20 14:26:04 +0100 (Thu, 20 Jan 2005)
New Revision: 1728

Modified:
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/linux/drbd.h
   trunk/scripts/outdate-peer.sh
Log:
Kernel part of challenge/response authentication.
 [ completely untested... ] 


Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2005-01-19 21:24:55 UTC (rev 1727)
+++ trunk/drbd/drbd_fs.c	2005-01-20 13:26:04 UTC (rev 1728)
@@ -518,6 +518,7 @@
 	int i,minor;
 	enum ret_codes retcode;
 	struct net_config new_conf;
+	struct crypto_tfm* tfm = NULL;
 
 	minor=(int)(mdev-drbd_conf);
 
@@ -548,6 +549,20 @@
 #undef O_ADDR
 #undef O_PORT
 
+	if( new_conf.cram_hmac_alg[0] != 0) {
+		tfm = crypto_alloc_tfm(new_conf.cram_hmac_alg, 0);
+		if (tfm == NULL) {
+			retcode=CRAMAlgNotAvail;
+			goto fail_ioctl;
+		}
+	}
+
+	if ( mdev->cram_hmac_tfm ) {
+		crypto_free_tfm(mdev->cram_hmac_tfm);
+	}
+
+	mdev->cram_hmac_tfm = tfm;
+
 	/* IMPROVE:
 	   We should warn the user if the LL_DEV is
 	   used already. E.g. some FS mounted on it.
@@ -1076,6 +1091,11 @@
 		} 
 		/* r == 1 which means that we changed the state... */
 
+		if ( mdev->cram_hmac_tfm ) {
+			crypto_free_tfm(mdev->cram_hmac_tfm);
+			mdev->cram_hmac_tfm = NULL;
+		}
+
 		drbd_sync_me(mdev); /* FIXME what if fsync returns error */
 
 		drbd_thread_stop(&mdev->receiver);

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2005-01-19 21:24:55 UTC (rev 1727)
+++ trunk/drbd/drbd_int.h	2005-01-20 13:26:04 UTC (rev 1728)
@@ -33,7 +33,7 @@
 #include <linux/sched.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
-
+#include <linux/crypto.h>
 #include "lru_cache.h"
 
 // module parameter, defined in drbd_main.c
@@ -295,6 +295,8 @@
 	ReportGenCnt,
 	ReportSizes,
 	ReportState,
+	AuthChallenge,
+	AuthResponse,
 
 	Ping,         // These are sent on the meta socket...
 	PingAck,
@@ -333,6 +335,8 @@
 		[ReportGenCnt]     = "ReportGenCnt",
 		[ReportSizes]      = "ReportSizes",
 		[ReportState]      = "ReportState",
+		[AuthChallenge]    = "AuthChallenge",
+		[AuthResponse]     = "AuthResponse",
 		[Ping]             = "Ping",
 		[PingAck]          = "PingAck",
 		[RecvAck]          = "RecvAck",
@@ -742,6 +746,7 @@
 	unsigned int al_tr_number;
 	int al_tr_cycle;
 	int al_tr_pos;     // position of the next transaction in the journal
+	struct crypto_tfm* cram_hmac_tfm;
 };
 
 
@@ -779,6 +784,8 @@
 			  size_t size, unsigned msg_flags);
 extern int drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
 			  Drbd_Packet_Cmd cmd, Drbd_Header *h, size_t size);
+extern int drbd_send_cmd2(drbd_dev *mdev, Drbd_Packet_Cmd cmd, 
+			  char* data, size_t size);
 extern int drbd_send_sync_param(drbd_dev *mdev, struct syncer_config *sc);
 extern int drbd_send_b_ack(drbd_dev *mdev, u32 barrier_nr,
 			   u32 set_size);

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2005-01-19 21:24:55 UTC (rev 1727)
+++ trunk/drbd/drbd_main.c	2005-01-20 13:26:04 UTC (rev 1728)
@@ -807,6 +807,33 @@
 	return ok;
 }
 
+int drbd_send_cmd2(drbd_dev *mdev, Drbd_Packet_Cmd cmd, char* data, 
+		   size_t size)
+{
+	sigset_t old_blocked;
+	Drbd_Header h;
+	int ok;
+
+	down(&mdev->data.mutex);
+	spin_lock(&mdev->send_task_lock);
+	mdev->send_task=current;
+	spin_unlock(&mdev->send_task_lock);
+
+	old_blocked = drbd_block_all_signals();
+
+	ok = _drbd_send_cmd(mdev,mdev->data.socket,cmd,&h,size,0);
+	ok = ok && ( size == drbd_send(mdev,mdev->data.socket,data,size,0) );
+
+	restore_old_sigset(old_blocked);
+
+	spin_lock(&mdev->send_task_lock);
+	mdev->send_task=NULL;
+	spin_unlock(&mdev->send_task_lock);
+	up(&mdev->data.mutex);
+
+	return ok;
+}
+
 int drbd_send_sync_param(drbd_dev *mdev, struct syncer_config *sc)
 {
 	Drbd_SyncParam_Packet p;
@@ -2031,6 +2058,10 @@
 
 void drbd_free_resources(drbd_dev *mdev)
 {
+	if ( mdev->cram_hmac_tfm ) {
+		crypto_free_tfm(mdev->cram_hmac_tfm);
+		mdev->cram_hmac_tfm = NULL;
+	}
 	drbd_free_sock(mdev);
 	drbd_free_ll_dev(mdev);
 }

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2005-01-19 21:24:55 UTC (rev 1727)
+++ trunk/drbd/drbd_receiver.c	2005-01-20 13:26:04 UTC (rev 1728)
@@ -47,6 +47,7 @@
 #define __KERNEL_SYSCALLS__
 #include <linux/unistd.h>
 #include <linux/vmalloc.h>
+#include <linux/random.h>
 #include <linux/drbd.h>
 #include "drbd_int.h"
 
@@ -616,6 +617,7 @@
 }
 
 STATIC int drbd_do_handshake(drbd_dev *mdev);
+STATIC int drbd_do_auth(drbd_dev *mdev);
 
 int drbd_connect(drbd_dev *mdev)
 {
@@ -697,6 +699,13 @@
 		return 0;
 	}
 
+	if ( mdev->cram_hmac_tfm ) {
+		if (!drbd_do_auth(mdev)) {
+			ERR("Authentication of Peer failed.");
+			return 0;
+		}
+	}
+
 	clear_bit(ON_PRI_INC_HUMAN,&mdev->flags);
 	clear_bit(ON_PRI_INC_TIMEOUTEX,&mdev->flags);
 
@@ -1861,6 +1870,119 @@
 	return 1;
 }
 
+#ifndef CONFIG_CRYPTO_HMAC
+STATIC int drbd_do_auth(drbd_dev *mdev)
+{
+	ERR( "This kernel was build without CONFIG_CRYPTO_HMAC.\n");
+	ERR( "You need to disable 'cram-hmac-alg' in drbd.conf.\n");
+	return 0;
+}
+#else
+#define CHALLENGE_LEN 64
+STATIC int drbd_do_auth(drbd_dev *mdev)
+{
+	char my_challenge[CHALLENGE_LEN];  /* 64 Bytes... */
+	struct scatterlist sg;
+	char *response;
+	char *right_response;
+	char *peers_ch;
+	Drbd_Header p;
+	unsigned int key_len = SHARED_SECRET_MAX;
+	unsigned int resp_size;
+	int rv;
+	
+	get_random_bytes(my_challenge, CHALLENGE_LEN);
+	
+	rv = drbd_send_cmd2(mdev,AuthChallenge,my_challenge,CHALLENGE_LEN);
+	if (!rv) return 0;
+
+	rv = drbd_recv_header(mdev,&p);
+	if (!rv) return 0;
+
+	if (p.command != AuthChallenge) {
+		ERR( "expected AuthChallenge packet, received: %s (0x%04x)\n",
+		     cmdname(p.command), p.command );
+		return 0;
+	}
+
+	if (p.length > CHALLENGE_LEN*2 ) {
+	  ERR( "expected AuthChallenge payload too big.\n");
+		return 0;
+	}
+
+	peers_ch = kmalloc(p.length,GFP_KERNEL);
+	if(peers_ch == NULL) {
+		ERR("kmalloc of peers_ch failed\n");
+		return 0;
+	}
+
+	rv = drbd_recv(mdev, peers_ch, p.length);
+
+	if (rv != p.length) {
+		ERR("short read AuthChallenge: l=%u\n", rv);
+		return 0;
+	}
+
+	resp_size = crypto_tfm_alg_digestsize(mdev->cram_hmac_tfm);
+	response = kmalloc(resp_size,GFP_KERNEL);
+	if(response == NULL) {
+		ERR("kmalloc of response failed\n");
+		return 0;
+	}
+
+	sg.page   = virt_to_page(peers_ch);
+	sg.offset = offset_in_page(peers_ch);
+	sg.length = p.length;
+	crypto_hmac(mdev->cram_hmac_tfm, (u8*)mdev->conf.shared_secret,
+		    &key_len, &sg, 1, response);
+
+	kfree(peers_ch);
+
+	rv = drbd_send_cmd2(mdev,AuthResponse,response,resp_size);
+	if (!rv) return 0;
+
+	rv = drbd_recv_header(mdev,&p);
+	if (!rv) return 0;
+
+	if (p.command != AuthResponse) {
+		ERR( "expected AuthResponse packet, received: %s (0x%04x)\n",
+		     cmdname(p.command), p.command );
+		return 0;
+	}
+
+	if (p.length != resp_size ) {
+		ERR( "expected AuthResponse payload of wrong size.\n" );
+		return 0;
+	}
+
+	rv = drbd_recv(mdev, response , resp_size);
+
+	if (rv != resp_size) {
+		ERR("short read receiving AuthResponse: l=%u\n", rv);
+		return 0;
+	}
+
+	right_response = kmalloc(resp_size,GFP_KERNEL);
+	if(response == NULL) {
+		ERR("kmalloc of right_response failed\n");
+		return 0;
+	}
+	
+	sg.page   = virt_to_page(my_challenge);
+	sg.offset = offset_in_page(my_challenge);
+	sg.length = CHALLENGE_LEN;
+	crypto_hmac(mdev->cram_hmac_tfm, (u8*)mdev->conf.shared_secret,
+		    &key_len, &sg, 1, right_response);
+
+	rv = ! memcmp(response,right_response,resp_size);
+	
+	kfree(response);
+	kfree(right_response);
+
+	return rv;
+}
+#endif
+
 int drbdd_init(struct Drbd_thread *thi)
 {
 	drbd_dev *mdev = thi->mdev;

Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h	2005-01-19 21:24:55 UTC (rev 1727)
+++ trunk/drbd/linux/drbd.h	2005-01-20 13:26:04 UTC (rev 1728)
@@ -134,6 +134,7 @@
 	LDDeviceTooLarge,
 	MDIOError,
 	MDInvalid,
+	CRAMAlgNotAvail,
 };
 
 struct ioctl_disk_config {

Modified: trunk/scripts/outdate-peer.sh
===================================================================
--- trunk/scripts/outdate-peer.sh	2005-01-19 21:24:55 UTC (rev 1727)
+++ trunk/scripts/outdate-peer.sh	2005-01-20 13:26:04 UTC (rev 1728)
@@ -30,7 +30,7 @@
 #    time it asks you if it should ad the fingerprint to the list
 #    of known hosts: Say yes here.
 #
-# 4. To this a second time for each IP address, now it should not ask
+# 4. Do this a second time for each IP address, now it should not ask
 #    any questions...
 #
 # Repeate this 4 steps for the other direction, BTW, you can not



More information about the drbd-cvs mailing list