xdmauth.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. /*
  2. Copyright 1988, 1998 The Open Group
  3. Permission to use, copy, modify, distribute, and sell this software and its
  4. documentation for any purpose is hereby granted without fee, provided that
  5. the above copyright notice appear in all copies and that both that
  6. copyright notice and this permission notice appear in supporting
  7. documentation.
  8. The above copyright notice and this permission notice shall be included
  9. in all copies or substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  11. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  12. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  13. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
  14. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  15. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  16. OTHER DEALINGS IN THE SOFTWARE.
  17. Except as contained in this notice, the name of The Open Group shall
  18. not be used in advertising or otherwise to promote the sale, use or
  19. other dealings in this Software without prior written authorization
  20. from The Open Group.
  21. */
  22. /*
  23. * XDM-AUTHENTICATION-1 (XDMCP authentication) and
  24. * XDM-AUTHORIZATION-1 (client authorization) protocols
  25. *
  26. * Author: Keith Packard, MIT X Consortium
  27. */
  28. #ifdef HAVE_DIX_CONFIG_H
  29. #include <dix-config.h>
  30. #endif
  31. #include <stdio.h>
  32. #include <X11/X.h>
  33. #define XSERV_t
  34. #define TRANS_SERVER
  35. #define TRANS_REOPEN
  36. #include <X11/Xtrans/Xtrans.h>
  37. #include "os.h"
  38. #include "osdep.h"
  39. #include "dixstruct.h"
  40. #ifdef HASXDMAUTH
  41. static Bool authFromXDMCP;
  42. #ifdef XDMCP
  43. #include <X11/Xmd.h>
  44. #undef REQUEST
  45. #include <X11/Xdmcp.h>
  46. /* XDM-AUTHENTICATION-1 */
  47. static XdmAuthKeyRec privateKey;
  48. static const char XdmAuthenticationName[] = "XDM-AUTHENTICATION-1";
  49. #define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1)
  50. static XdmAuthKeyRec rho;
  51. static Bool
  52. XdmAuthenticationValidator (ARRAY8Ptr privateData, ARRAY8Ptr incomingData,
  53. xdmOpCode packet_type)
  54. {
  55. XdmAuthKeyPtr incoming;
  56. XdmcpUnwrap (incomingData->data, (unsigned char *) &privateKey,
  57. incomingData->data,incomingData->length);
  58. if (packet_type == ACCEPT) {
  59. if (incomingData->length != 8)
  60. return FALSE;
  61. incoming = (XdmAuthKeyPtr) incomingData->data;
  62. XdmcpDecrementKey (incoming);
  63. return XdmcpCompareKeys (incoming, &rho);
  64. }
  65. return FALSE;
  66. }
  67. static Bool
  68. XdmAuthenticationGenerator (ARRAY8Ptr privateData, ARRAY8Ptr outgoingData,
  69. xdmOpCode packet_type)
  70. {
  71. outgoingData->length = 0;
  72. outgoingData->data = 0;
  73. if (packet_type == REQUEST) {
  74. if (XdmcpAllocARRAY8 (outgoingData, 8))
  75. XdmcpWrap((unsigned char *) &rho, (unsigned char *) &privateKey,
  76. outgoingData->data, 8);
  77. }
  78. return TRUE;
  79. }
  80. static Bool
  81. XdmAuthenticationAddAuth (int name_len, const char *name,
  82. int data_len, char *data)
  83. {
  84. Bool ret;
  85. XdmcpUnwrap((unsigned char *) data, (unsigned char *) &privateKey,
  86. (unsigned char *) data, data_len);
  87. authFromXDMCP = TRUE;
  88. ret = AddAuthorization (name_len, name, data_len, data);
  89. authFromXDMCP = FALSE;
  90. return ret;
  91. }
  92. #define atox(c) ('0' <= c && c <= '9' ? c - '0' : \
  93. 'a' <= c && c <= 'f' ? c - 'a' + 10 : \
  94. 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
  95. static int
  96. HexToBinary (const char *in, char *out, int len)
  97. {
  98. int top, bottom;
  99. while (len > 0)
  100. {
  101. top = atox(in[0]);
  102. if (top == -1)
  103. return 0;
  104. bottom = atox(in[1]);
  105. if (bottom == -1)
  106. return 0;
  107. *out++ = (top << 4) | bottom;
  108. in += 2;
  109. len -= 2;
  110. }
  111. if (len)
  112. return 0;
  113. *out++ = '\0';
  114. return 1;
  115. }
  116. void
  117. XdmAuthenticationInit(const char *cookie, int cookie_len)
  118. {
  119. memset(privateKey.data, 0, 8);
  120. if (!strncmp (cookie, "0x", 2) || !strncmp (cookie, "0X", 2))
  121. {
  122. if (cookie_len > 2 + 2 * 8)
  123. cookie_len = 2 + 2 * 8;
  124. HexToBinary (cookie + 2, (char *)privateKey.data, cookie_len - 2);
  125. }
  126. else
  127. {
  128. if (cookie_len > 7)
  129. cookie_len = 7;
  130. memmove (privateKey.data + 1, cookie, cookie_len);
  131. }
  132. XdmcpGenerateKey (&rho);
  133. XdmcpRegisterAuthentication (XdmAuthenticationName, XdmAuthenticationNameLen,
  134. (char *)&rho,
  135. sizeof (rho),
  136. (ValidatorFunc)XdmAuthenticationValidator,
  137. (GeneratorFunc)XdmAuthenticationGenerator,
  138. (AddAuthorFunc)XdmAuthenticationAddAuth);
  139. }
  140. #endif /* XDMCP */
  141. /* XDM-AUTHORIZATION-1 */
  142. typedef struct _XdmAuthorization {
  143. struct _XdmAuthorization *next;
  144. XdmAuthKeyRec rho;
  145. XdmAuthKeyRec key;
  146. XID id;
  147. } XdmAuthorizationRec, *XdmAuthorizationPtr;
  148. static XdmAuthorizationPtr xdmAuth;
  149. typedef struct _XdmClientAuth {
  150. struct _XdmClientAuth *next;
  151. XdmAuthKeyRec rho;
  152. char client[6];
  153. long time;
  154. } XdmClientAuthRec, *XdmClientAuthPtr;
  155. static XdmClientAuthPtr xdmClients;
  156. static long clockOffset;
  157. static Bool gotClock;
  158. #define TwentyMinutes (20 * 60)
  159. #define TwentyFiveMinutes (25 * 60)
  160. static Bool
  161. XdmClientAuthCompare(const XdmClientAuthPtr a, const XdmClientAuthPtr b)
  162. {
  163. int i;
  164. if (!XdmcpCompareKeys (&a->rho, &b->rho))
  165. return FALSE;
  166. for (i = 0; i < 6; i++)
  167. if (a->client[i] != b->client[i])
  168. return FALSE;
  169. return a->time == b->time;
  170. }
  171. static void
  172. XdmClientAuthDecode(const unsigned char *plain, XdmClientAuthPtr auth)
  173. {
  174. int i, j;
  175. j = 0;
  176. for (i = 0; i < 8; i++)
  177. {
  178. auth->rho.data[i] = plain[j];
  179. ++j;
  180. }
  181. for (i = 0; i < 6; i++)
  182. {
  183. auth->client[i] = plain[j];
  184. ++j;
  185. }
  186. auth->time = 0;
  187. for (i = 0; i < 4; i++)
  188. {
  189. auth->time |= plain[j] << ((3 - i) << 3);
  190. j++;
  191. }
  192. }
  193. static void
  194. XdmClientAuthTimeout (long now)
  195. {
  196. XdmClientAuthPtr client, next, prev;
  197. prev = 0;
  198. for (client = xdmClients; client; client=next)
  199. {
  200. next = client->next;
  201. if (abs (now - client->time) > TwentyFiveMinutes)
  202. {
  203. if (prev)
  204. prev->next = next;
  205. else
  206. xdmClients = next;
  207. free(client);
  208. }
  209. else
  210. prev = client;
  211. }
  212. }
  213. static XdmClientAuthPtr
  214. XdmAuthorizationValidate (unsigned char *plain, int length,
  215. XdmAuthKeyPtr rho, ClientPtr xclient, const char **reason)
  216. {
  217. XdmClientAuthPtr client, existing;
  218. long now;
  219. int i;
  220. if (length != (192 / 8)) {
  221. if (reason)
  222. *reason = "Bad XDM authorization key length";
  223. return NULL;
  224. }
  225. client = malloc(sizeof (XdmClientAuthRec));
  226. if (!client)
  227. return NULL;
  228. XdmClientAuthDecode (plain, client);
  229. if (!XdmcpCompareKeys (&client->rho, rho))
  230. {
  231. free(client);
  232. if (reason)
  233. *reason = "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)";
  234. return NULL;
  235. }
  236. for (i = 18; i < 24; i++)
  237. if (plain[i] != 0) {
  238. free(client);
  239. if (reason)
  240. *reason = "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)";
  241. return NULL;
  242. }
  243. if (xclient) {
  244. int family, addr_len;
  245. Xtransaddr *addr;
  246. if (_XSERVTransGetPeerAddr(((OsCommPtr)xclient->osPrivate)->trans_conn,
  247. &family, &addr_len, &addr) == 0
  248. && _XSERVTransConvertAddress(&family, &addr_len, &addr) == 0) {
  249. #if defined(TCPCONN)
  250. if (family == FamilyInternet &&
  251. memcmp((char *)addr, client->client, 4) != 0) {
  252. free(client);
  253. free(addr);
  254. if (reason)
  255. *reason = "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)";
  256. return NULL;
  257. }
  258. #endif
  259. free(addr);
  260. }
  261. }
  262. now = time(0);
  263. if (!gotClock)
  264. {
  265. clockOffset = client->time - now;
  266. gotClock = TRUE;
  267. }
  268. now += clockOffset;
  269. XdmClientAuthTimeout (now);
  270. if (abs (client->time - now) > TwentyMinutes)
  271. {
  272. free(client);
  273. if (reason)
  274. *reason = "Excessive XDM-AUTHORIZATION-1 time offset";
  275. return NULL;
  276. }
  277. for (existing = xdmClients; existing; existing=existing->next)
  278. {
  279. if (XdmClientAuthCompare (existing, client))
  280. {
  281. free(client);
  282. if (reason)
  283. *reason = "XDM authorization key matches an existing client!";
  284. return NULL;
  285. }
  286. }
  287. return client;
  288. }
  289. int
  290. XdmAddCookie (unsigned short data_length, const char *data, XID id)
  291. {
  292. XdmAuthorizationPtr new;
  293. unsigned char *rho_bits, *key_bits;
  294. switch (data_length)
  295. {
  296. case 16: /* auth from files is 16 bytes long */
  297. #ifdef XDMCP
  298. if (authFromXDMCP)
  299. {
  300. /* R5 xdm sent bogus authorization data in the accept packet,
  301. * but we can recover */
  302. rho_bits = rho.data;
  303. key_bits = (unsigned char *) data;
  304. key_bits[0] = '\0';
  305. }
  306. else
  307. #endif
  308. {
  309. rho_bits = (unsigned char *) data;
  310. key_bits = (unsigned char *) (data + 8);
  311. }
  312. break;
  313. #ifdef XDMCP
  314. case 8: /* auth from XDMCP is 8 bytes long */
  315. rho_bits = rho.data;
  316. key_bits = (unsigned char *) data;
  317. break;
  318. #endif
  319. default:
  320. return 0;
  321. }
  322. /* the first octet of the key must be zero */
  323. if (key_bits[0] != '\0')
  324. return 0;
  325. new = malloc(sizeof (XdmAuthorizationRec));
  326. if (!new)
  327. return 0;
  328. new->next = xdmAuth;
  329. xdmAuth = new;
  330. memmove (new->key.data, key_bits, (int) 8);
  331. memmove (new->rho.data, rho_bits, (int) 8);
  332. new->id = id;
  333. return 1;
  334. }
  335. XID
  336. XdmCheckCookie (unsigned short cookie_length, const char *cookie,
  337. ClientPtr xclient, const char **reason)
  338. {
  339. XdmAuthorizationPtr auth;
  340. XdmClientAuthPtr client;
  341. unsigned char *plain;
  342. /* Auth packets must be a multiple of 8 bytes long */
  343. if (cookie_length & 7)
  344. return (XID) -1;
  345. plain = malloc(cookie_length);
  346. if (!plain)
  347. return (XID) -1;
  348. for (auth = xdmAuth; auth; auth=auth->next) {
  349. XdmcpUnwrap ((unsigned char *) cookie, (unsigned char *)&auth->key,
  350. plain, cookie_length);
  351. if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, xclient, reason)) != NULL)
  352. {
  353. client->next = xdmClients;
  354. xdmClients = client;
  355. free(plain);
  356. return auth->id;
  357. }
  358. }
  359. free(plain);
  360. return (XID) -1;
  361. }
  362. int
  363. XdmResetCookie (void)
  364. {
  365. XdmAuthorizationPtr auth, next_auth;
  366. XdmClientAuthPtr client, next_client;
  367. for (auth = xdmAuth; auth; auth=next_auth)
  368. {
  369. next_auth = auth->next;
  370. free(auth);
  371. }
  372. xdmAuth = 0;
  373. for (client = xdmClients; client; client=next_client)
  374. {
  375. next_client = client->next;
  376. free(client);
  377. }
  378. xdmClients = (XdmClientAuthPtr) 0;
  379. return 1;
  380. }
  381. XID
  382. XdmToID (unsigned short cookie_length, char *cookie)
  383. {
  384. XdmAuthorizationPtr auth;
  385. XdmClientAuthPtr client;
  386. unsigned char *plain;
  387. plain = malloc(cookie_length);
  388. if (!plain)
  389. return (XID) -1;
  390. for (auth = xdmAuth; auth; auth=auth->next) {
  391. XdmcpUnwrap ((unsigned char *) cookie, (unsigned char *)&auth->key,
  392. plain, cookie_length);
  393. if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, NULL, NULL)) != NULL)
  394. {
  395. free(client);
  396. free(cookie);
  397. free(plain);
  398. return auth->id;
  399. }
  400. }
  401. free(cookie);
  402. free(plain);
  403. return (XID) -1;
  404. }
  405. int
  406. XdmFromID (XID id, unsigned short *data_lenp, char **datap)
  407. {
  408. XdmAuthorizationPtr auth;
  409. for (auth = xdmAuth; auth; auth=auth->next) {
  410. if (id == auth->id) {
  411. *data_lenp = 16;
  412. *datap = (char *) &auth->rho;
  413. return 1;
  414. }
  415. }
  416. return 0;
  417. }
  418. int
  419. XdmRemoveCookie(unsigned short data_length, const char *data)
  420. {
  421. XdmAuthorizationPtr auth;
  422. XdmAuthKeyPtr key_bits, rho_bits;
  423. switch (data_length)
  424. {
  425. case 16:
  426. rho_bits = (XdmAuthKeyPtr) data;
  427. key_bits = (XdmAuthKeyPtr) (data + 8);
  428. break;
  429. #ifdef XDMCP
  430. case 8:
  431. rho_bits = &rho;
  432. key_bits = (XdmAuthKeyPtr) data;
  433. break;
  434. #endif
  435. default:
  436. return 0;
  437. }
  438. for (auth = xdmAuth; auth; auth=auth->next) {
  439. if (XdmcpCompareKeys (rho_bits, &auth->rho) &&
  440. XdmcpCompareKeys (key_bits, &auth->key))
  441. {
  442. xdmAuth = auth->next;
  443. free(auth);
  444. return 1;
  445. }
  446. }
  447. return 0;
  448. }
  449. #endif