Browse code

uac: use auth_ha1 field if set for remote registrations

- has priority over auth_password field

Daniel-Constantin Mierla authored on 02/09/2019 14:23:31
Showing 3 changed files
... ...
@@ -26,14 +26,17 @@
26 26
 
27 27
 #include "../../core/parser/msg_parser.h"
28 28
 
29
-struct uac_credential {
29
+#define UAC_FLCRED_HA1 (1<<0)
30
+
31
+typedef struct uac_credential {
30 32
 	str realm;
31 33
 	str user;
32 34
 	str passwd;
35
+	uint32_t aflags;
33 36
 	struct uac_credential *next;
34
-};
37
+} uac_credential_t;
35 38
 
36
-struct authenticate_body {
39
+typedef struct authenticate_body {
37 40
 	int flags;
38 41
 	str realm;
39 42
 	str domain;
... ...
@@ -42,7 +45,7 @@ struct authenticate_body {
42 45
 	str qop;
43 46
 	str *nc;
44 47
 	str *cnonce;
45
-};
48
+} uac_authenticate_body_t;
46 49
 
47 50
 #define AUTHENTICATE_MD5         (1<<0)
48 51
 #define AUTHENTICATE_MD5SESS     (1<<1)
... ...
@@ -61,8 +61,31 @@ static inline void cvt_hex(HASH bin, HASHHEX hex)
61 61
 }
62 62
 
63 63
 
64
+static inline void cvt_bin(HASHHEX hex, HASH bin)
65
+{
66
+	unsigned short i;
67
+	unsigned char j;
68
+	for (i = 0; i<HASHLEN; i++) {
69
+		if(hex[2*i]>='0' && hex[2*i]<='9')
70
+			j = (hex[2*i]-'0') << 4;
71
+		else if(hex[2*i]>='a'&&hex[2*i]<='f')
72
+			j = (hex[2*i]-'a'+10) << 4;
73
+		else if(hex[2*i]>='A'&&hex[2*i]<='F')
74
+			j = (hex[2*i]-'A'+10) << 4;
75
+		else j = 0;
76
+
77
+		if(hex[2*i+1]>='0'&&hex[2*i+1]<='9')
78
+			j += hex[2*i+1]-'0';
79
+		else if(hex[2*i+1]>='a'&&hex[2*i+1]<='f')
80
+			j += hex[2*i+1]-'a'+10;
81
+		else if(hex[2*i+1]>='A'&&hex[2*i+1]<='F')
82
+			j += hex[2*i+1]-'A'+10;
83
+
84
+		bin[i] = j;
85
+	}
86
+}
64 87
 
65
-/* 
88
+/*
66 89
  * calculate H(A1)
67 90
  */
68 91
 void uac_calc_HA1( struct uac_credential *crd,
... ...
@@ -73,16 +96,25 @@ void uac_calc_HA1( struct uac_credential *crd,
73 96
 	MD5_CTX Md5Ctx;
74 97
 	HASH HA1;
75 98
 
76
-	MD5Init(&Md5Ctx);
77
-	MD5Update(&Md5Ctx, crd->user.s, crd->user.len);
78
-	MD5Update(&Md5Ctx, ":", 1);
79
-	MD5Update(&Md5Ctx, crd->realm.s, crd->realm.len);
80
-	MD5Update(&Md5Ctx, ":", 1);
81
-	MD5Update(&Md5Ctx, crd->passwd.s, crd->passwd.len);
82
-	MD5Final(HA1, &Md5Ctx);
99
+	if(UAC_FLCRED_HA1 & UAC_FLCRED_HA1) {
100
+		memcpy(sess_key, crd->passwd.s, HASHHEXLEN);
101
+		sess_key[HASHHEXLEN] = '\0';
102
+		if ( auth->flags& AUTHENTICATE_MD5SESS ) {
103
+			cvt_bin(sess_key, HA1);
104
+		} else {
105
+			return;
106
+		}
107
+	} else {
108
+		MD5Init(&Md5Ctx);
109
+		MD5Update(&Md5Ctx, crd->user.s, crd->user.len);
110
+		MD5Update(&Md5Ctx, ":", 1);
111
+		MD5Update(&Md5Ctx, crd->realm.s, crd->realm.len);
112
+		MD5Update(&Md5Ctx, ":", 1);
113
+		MD5Update(&Md5Ctx, crd->passwd.s, crd->passwd.len);
114
+		MD5Final(HA1, &Md5Ctx);
115
+	}
83 116
 
84
-	if ( auth->flags& AUTHENTICATE_MD5SESS )
85
-	{
117
+	if ( auth->flags& AUTHENTICATE_MD5SESS ) {
86 118
 		MD5Init(&Md5Ctx);
87 119
 		MD5Update(&Md5Ctx, HA1, HASHLEN);
88 120
 		MD5Update(&Md5Ctx, ":", 1);
... ...
@@ -90,7 +122,7 @@ void uac_calc_HA1( struct uac_credential *crd,
90 122
 		MD5Update(&Md5Ctx, ":", 1);
91 123
 		MD5Update(&Md5Ctx, cnonce->s, cnonce->len);
92 124
 		MD5Final(HA1, &Md5Ctx);
93
-	};
125
+	}
94 126
 
95 127
 	cvt_hex(HA1, sess_key);
96 128
 }
... ...
@@ -75,6 +75,7 @@ typedef struct _reg_uac
75 75
 	str   auth_proxy;
76 76
 	str   auth_username;
77 77
 	str   auth_password;
78
+	str   auth_ha1;
78 79
 	str   callid;
79 80
 	str   socket;
80 81
 	unsigned int cseq;
... ...
@@ -133,6 +134,7 @@ str r_domain_column = str_init("r_domain");
133 134
 str realm_column = str_init("realm");
134 135
 str auth_username_column = str_init("auth_username");
135 136
 str auth_password_column = str_init("auth_password");
137
+str auth_ha1_column = str_init("auth_ha1");
136 138
 str auth_proxy_column = str_init("auth_proxy");
137 139
 str expires_column = str_init("expires");
138 140
 str flags_column = str_init("flags");
... ...
@@ -513,6 +515,7 @@ int reg_ht_add(reg_uac_t *reg)
513 515
 	int len;
514 516
 	reg_uac_t *nr = NULL;
515 517
 	char *p;
518
+	int i;
516 519
 
517 520
 	if(reg==NULL || _reg_htable==NULL)
518 521
 	{
... ...
@@ -528,6 +531,7 @@ int reg_ht_add(reg_uac_t *reg)
528 531
 		+ reg->auth_proxy.len + 1
529 532
 		+ reg->auth_username.len + 1
530 533
 		+ reg->auth_password.len + 1
534
+		+ reg->auth_ha1.len + 1
531 535
 		+ reg->socket.len + 1
532 536
 		+ (reg_keep_callid ? UAC_REG_TM_CALLID_SIZE : 0) + 1;
533 537
 	nr = (reg_uac_t*)shm_malloc(sizeof(reg_uac_t) + len);
... ...
@@ -558,9 +562,17 @@ int reg_ht_add(reg_uac_t *reg)
558 562
 	reg_copy_shm(&nr->auth_proxy, &reg->auth_proxy, 0);
559 563
 	reg_copy_shm(&nr->auth_username, &reg->auth_username, 0);
560 564
 	reg_copy_shm(&nr->auth_password, &reg->auth_password, 0);
565
+	reg_copy_shm(&nr->auth_ha1, &reg->auth_ha1, 0);
561 566
 	reg_copy_shm(&nr->socket, &reg->socket, 0);
562 567
 	reg_copy_shm(&nr->callid, &str_empty, reg_keep_callid ? UAC_REG_TM_CALLID_SIZE : 0);
563 568
 
569
+	for(i=0; i<nr->auth_ha1.len; i++) {
570
+		/* ha1 to lowercase */
571
+		if(nr->auth_ha1.s[i] >= 'A' && nr->auth_ha1.s[i] <= 'F') {
572
+			nr->auth_ha1.s[i] += 32;
573
+		}
574
+	}
575
+
564 576
 	reg_ht_add_byuser(nr);
565 577
 	reg_ht_add_byuuid(nr);
566 578
 	counter_inc(regtotal);
... ...
@@ -810,7 +822,7 @@ void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
810 822
 	HASHHEX response;
811 823
 	str *new_auth_hdr = NULL;
812 824
 	static struct authenticate_body auth;
813
-	struct uac_credential cred;
825
+	uac_credential_t cred;
814 826
 	char  b_ruri[MAX_URI_SIZE];
815 827
 	str   s_ruri;
816 828
 	char  b_hdrs[MAX_UACH_SIZE];
... ...
@@ -936,9 +948,15 @@ void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
936 948
 				goto error;
937 949
 			}
938 950
 		}
951
+		cred.aflags = 0;
939 952
 		cred.realm = auth.realm;
940 953
 		cred.user = ri->auth_username;
941
-		cred.passwd = ri->auth_password;
954
+		if(ri->auth_ha1.len > 0) {
955
+			cred.passwd = ri->auth_ha1;
956
+			cred.aflags |= UAC_FLCRED_HA1;
957
+		} else {
958
+			cred.passwd = ri->auth_password;
959
+		}
942 960
 		cred.next = NULL;
943 961
 
944 962
 		snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s",
... ...
@@ -1206,45 +1224,75 @@ void uac_reg_timer(unsigned int ticks)
1206 1224
 	}
1207 1225
 }
1208 1226
 
1209
-#define reg_db_set_attr(attr, pos) do { \
1227
+static int uac_reg_check_password(reg_uac_t *reg)
1228
+{
1229
+	int i;
1230
+
1231
+	if(reg->auth_password.len<=0 && reg->auth_ha1.len<=0) {
1232
+		LM_ERR("no password value provided - ignoring record\n");
1233
+		return -1;
1234
+	}
1235
+
1236
+	if(reg->auth_ha1.len > 0 && reg->auth_ha1.len != HASHHEXLEN) {
1237
+		LM_ERR("invalid HA2 length: %d - ignoring record\n", reg->auth_ha1.len);
1238
+		return -1;
1239
+	}
1240
+	for(i=0; i<reg->auth_ha1.len; i++) {
1241
+		if(!((reg->auth_ha1.s[i]>='0' && reg->auth_ha1.s[i]<'9')
1242
+				|| (reg->auth_ha1.s[i]>='a' && reg->auth_ha1.s[i]<='f')
1243
+				|| (reg->auth_ha1.s[i]>='A' && reg->auth_ha1.s[i]<='F'))) {
1244
+			LM_ERR("invalid char %d in HA1 string: %.*s\n", i,
1245
+					reg->auth_ha1.len, reg->auth_ha1.s);
1246
+			return -1;
1247
+		}
1248
+	}
1249
+
1250
+	return 0;
1251
+}
1252
+
1253
+#define reg_db_set_attr(attr, pos, eval) do { \
1210 1254
 	if(!VAL_NULL(&RES_ROWS(db_res)[i].values[pos])) { \
1211 1255
 		reg->attr.s = \
1212
-		(char*)(RES_ROWS(db_res)[i].values[pos].val.string_val); \
1256
+				(char*)(RES_ROWS(db_res)[i].values[pos].val.string_val); \
1213 1257
 		reg->attr.len = strlen(reg->attr.s); \
1214 1258
 		if(reg->attr.len == 0) { \
1215
-			LM_ERR("empty value not allowed for column[%d]='%.*s' - ignoring record\n", \
1216
-					pos, db_cols[pos]->len, db_cols[pos]->s); \
1217
-			return -1; \
1259
+			if(eval == 0) { \
1260
+				LM_ERR("empty value not allowed for column[%d]='%.*s' - ignoring record\n", \
1261
+						pos, db_cols[pos]->len, db_cols[pos]->s); \
1262
+				return -1; \
1263
+			}  else { \
1264
+				reg->attr.s = NULL; \
1265
+			} \
1218 1266
 		} \
1219 1267
 	} \
1220 1268
 } while(0);
1221 1269
 
1222 1270
 
1223
-static inline int uac_reg_db_to_reg(reg_uac_t *reg, db1_res_t* db_res, int i, db_key_t *db_cols)
1271
+static int uac_reg_db_to_reg(reg_uac_t *reg, db1_res_t* db_res, int i, db_key_t *db_cols)
1224 1272
 {
1225 1273
 	memset(reg, 0, sizeof(reg_uac_t));;
1226 1274
 	/* check for NULL values ?!?! */
1227
-	reg_db_set_attr(l_uuid, 0);
1228
-	reg_db_set_attr(l_username, 1);
1229
-	reg_db_set_attr(l_domain, 2);
1230
-	reg_db_set_attr(r_username, 3);
1231
-	reg_db_set_attr(r_domain, 4);
1275
+	reg_db_set_attr(l_uuid, 0, 0);
1276
+	reg_db_set_attr(l_username, 1, 0);
1277
+	reg_db_set_attr(l_domain, 2, 0);
1278
+	reg_db_set_attr(r_username, 3, 0);
1279
+	reg_db_set_attr(r_domain, 4, 0);
1232 1280
 	/* realm may be empty */
1233
-	if(!VAL_NULL(&RES_ROWS(db_res)[i].values[5])) {
1234
-		reg->realm.s = (char*)(RES_ROWS(db_res)[i].values[5].val.string_val);
1235
-		reg->realm.len = strlen(reg->realm.s);
1236
-	}
1237
-	reg_db_set_attr(auth_username, 6);
1238
-	reg_db_set_attr(auth_password, 7);
1239
-	reg_db_set_attr(auth_proxy, 8);
1240
-	reg->expires = (unsigned int)RES_ROWS(db_res)[i].values[9].val.int_val;
1241
-	reg->flags = (unsigned int)RES_ROWS(db_res)[i].values[10].val.int_val;
1242
-	reg->reg_delay = (unsigned int)RES_ROWS(db_res)[i].values[11].val.int_val;
1243
-	/* socket may be empty */
1244
-	if(!VAL_NULL(&RES_ROWS(db_res)[i].values[12])) {
1245
-		reg->socket.s = (char*)(RES_ROWS(db_res)[i].values[12].val.string_val);
1246
-		reg->socket.len = strlen(reg->socket.s);
1281
+	reg_db_set_attr(realm, 5, 1);
1282
+	reg_db_set_attr(auth_username, 6, 0);
1283
+	reg_db_set_attr(auth_password, 7, 1);
1284
+	reg_db_set_attr(auth_ha1, 8, 1);
1285
+	if(uac_reg_check_password(reg) < 0) {
1286
+		return -1;
1247 1287
 	}
1288
+	reg_db_set_attr(auth_proxy, 9, 0);
1289
+	reg->expires = (unsigned int)RES_ROWS(db_res)[i].values[10].val.int_val;
1290
+	reg->flags = (unsigned int)RES_ROWS(db_res)[i].values[11].val.int_val;
1291
+	reg->reg_delay = (unsigned int)RES_ROWS(db_res)[i].values[12].val.int_val;
1292
+
1293
+	/* socket may be empty */
1294
+	reg_db_set_attr(socket, 13, 1);
1295
+
1248 1296
 	return 0;
1249 1297
 }
1250 1298
 
... ...
@@ -1257,7 +1305,7 @@ int uac_reg_load_db(void)
1257 1305
 	db1_con_t *reg_db_con = NULL;
1258 1306
 	db_func_t reg_dbf;
1259 1307
 	reg_uac_t reg;
1260
-	db_key_t db_cols[13] = {
1308
+	db_key_t db_cols[14] = {
1261 1309
 		&l_uuid_column,
1262 1310
 		&l_username_column,
1263 1311
 		&l_domain_column,
... ...
@@ -1266,6 +1314,7 @@ int uac_reg_load_db(void)
1266 1314
 		&realm_column,
1267 1315
 		&auth_username_column,
1268 1316
 		&auth_password_column,
1317
+		&auth_ha1_column,
1269 1318
 		&auth_proxy_column,
1270 1319
 		&expires_column,
1271 1320
 		&flags_column,
... ...
@@ -1392,7 +1441,7 @@ int uac_reg_db_refresh(str *pl_uuid)
1392 1441
 	db_func_t reg_dbf;
1393 1442
 	reg_uac_t reg;
1394 1443
 	reg_uac_t *cur_reg;
1395
-	db_key_t db_cols[13] = {
1444
+	db_key_t db_cols[14] = {
1396 1445
 		&l_uuid_column,
1397 1446
 		&l_username_column,
1398 1447
 		&l_domain_column,
... ...
@@ -1401,6 +1450,7 @@ int uac_reg_db_refresh(str *pl_uuid)
1401 1450
 		&realm_column,
1402 1451
 		&auth_username_column,
1403 1452
 		&auth_password_column,
1453
+		&auth_ha1_column,
1404 1454
 		&auth_proxy_column,
1405 1455
 		&expires_column,
1406 1456
 		&flags_column,
... ...
@@ -1782,7 +1832,7 @@ static int rpc_uac_reg_add_node_helper(rpc_t* rpc, void* ctx, reg_uac_t *reg, ti
1782 1832
 		rpc->fault(ctx, 500, "Internal error creating rpc");
1783 1833
 		return -1;
1784 1834
 	}
1785
-	if (rpc->struct_add(th, "SSSSSSSSSddddddS",
1835
+	if (rpc->struct_add(th, "SSSSSSSSSSddddddS",
1786 1836
 				"l_uuid",        &reg->l_uuid,
1787 1837
 				"l_username",    &reg->l_username,
1788 1838
 				"l_domain",      &reg->l_domain,
... ...
@@ -1790,9 +1840,12 @@ static int rpc_uac_reg_add_node_helper(rpc_t* rpc, void* ctx, reg_uac_t *reg, ti
1790 1840
 				"r_domain",      &reg->r_domain,
1791 1841
 				"realm",         &reg->realm,
1792 1842
 				"auth_username", &reg->auth_username,
1793
-				"auth_password", &reg->auth_password,
1843
+				"auth_password", (reg->auth_password.len)?
1844
+										&reg->auth_password:&none,
1845
+				"auth_ha1",      (reg->auth_ha1.len)?
1846
+										&reg->auth_ha1:&none,
1794 1847
 				"auth_proxy",    (reg->auth_proxy.len)?
1795
-				&reg->auth_proxy:&none,
1848
+										&reg->auth_proxy:&none,
1796 1849
 				"expires",       (int)reg->expires,
1797 1850
 				"flags",         (int)reg->flags,
1798 1851
 				"diff_expires",  (int)(reg->timer_expires - tn),
... ...
@@ -2043,7 +2096,7 @@ static void rpc_uac_reg_add(rpc_t* rpc, void* ctx)
2043 2096
 	reg_uac_t reg;
2044 2097
 	reg_uac_t *cur_reg;
2045 2098
 
2046
-	if(rpc->scan(ctx, "SSSSSSSSSdddS",
2099
+	if(rpc->scan(ctx, "SSSSSSSSSSdddS",
2047 2100
 				&reg.l_uuid,
2048 2101
 				&reg.l_username,
2049 2102
 				&reg.l_domain,
... ...
@@ -2052,6 +2105,7 @@ static void rpc_uac_reg_add(rpc_t* rpc, void* ctx)
2052 2105
 				&reg.realm,
2053 2106
 				&reg.auth_username,
2054 2107
 				&reg.auth_password,
2108
+				&reg.auth_ha1,
2055 2109
 				&reg.auth_proxy,
2056 2110
 				&reg.expires,
2057 2111
 				&reg.flags,
... ...
@@ -2063,6 +2117,21 @@ static void rpc_uac_reg_add(rpc_t* rpc, void* ctx)
2063 2117
 		return;
2064 2118
 	}
2065 2119
 
2120
+	if(reg.auth_password.len==1 && reg.auth_password.s[0] == '.') {
2121
+		reg.auth_password.s = NULL;
2122
+		reg.auth_password.len = 0;
2123
+	}
2124
+
2125
+	if(reg.auth_ha1.len==1 && reg.auth_ha1.s[0] == '.') {
2126
+		reg.auth_ha1.s = NULL;
2127
+		reg.auth_ha1.len = 0;
2128
+	}
2129
+
2130
+	if(uac_reg_check_password(&reg) < 0) {
2131
+		rpc->fault(ctx, 500, "Failed to add record - invalid password or ha1");
2132
+		return;
2133
+	}
2134
+
2066 2135
 	cur_reg = reg_ht_get_byuuid(&reg.l_uuid);
2067 2136
 	if (cur_reg) {
2068 2137
 		lock_release(cur_reg->lock);