PageRenderTime 60ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Library/ShadowPath/ShadowPath/Antinat/server/auth.m

https://gitlab.com/longkas/Potatso-iOS
Objective C | 578 lines | 514 code | 38 blank | 26 comment | 93 complexity | c9b8351982b3c180921cdd4a5edcc082 MD5 | raw file
  1. /* ANTINAT
  2. * =======
  3. * This software is Copyright (c) 2003-04 Malcolm Smith.
  4. * No warranty is provided, including but not limited to
  5. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  6. * This code is licenced subject to the GNU General
  7. * Public Licence (GPL). See the COPYING file for more.
  8. */
  9. #include "an_serv.h"
  10. #include "antinat.h"
  11. #ifdef HAVE_CRYPT_H
  12. #include <crypt.h>
  13. #endif
  14. #ifdef HAVE_PWD_H
  15. #include <pwd.h>
  16. #endif
  17. #ifdef HAVE_SHADOW_H
  18. #include <shadow.h>
  19. #endif
  20. static BOOL
  21. auth_config_getpw (config_t * conf, const char *username, char **passwd)
  22. {
  23. const char *realpasswd;
  24. char *tmp;
  25. BOOL authed;
  26. #ifdef WITH_DEBUG
  27. char szDebug[300];
  28. #endif
  29. authed = FALSE;
  30. realpasswd = NULL;
  31. realpasswd = config_getUser (conf, username);
  32. #ifdef WITH_DEBUG
  33. if (realpasswd)
  34. sprintf (szDebug, "Found user, has hash %s", realpasswd);
  35. else
  36. sprintf (szDebug, "Username not found - %s", username);
  37. DEBUG_LOG (szDebug);
  38. #endif
  39. if (realpasswd) {
  40. tmp = (char *) malloc (strlen (realpasswd) + 1);
  41. if (tmp != NULL) {
  42. strcpy (tmp, realpasswd);
  43. *passwd = tmp;
  44. return TRUE;
  45. }
  46. }
  47. return FALSE;
  48. }
  49. static BOOL
  50. auth_getPasswordByUsername (config_t * conf, const char *username,
  51. char **passwd)
  52. {
  53. /* This is a placeholder so we can support more datasources. */
  54. return auth_config_getpw (conf, username, passwd);
  55. }
  56. static const char lets[] =
  57. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwyxz0123456789+/";
  58. static BOOL
  59. auth_chap_gen_challenge (char *data, int len)
  60. {
  61. int i;
  62. for (i = 0; i < len; i++) {
  63. data[i] = lets[rand () % 64];
  64. }
  65. return TRUE;
  66. }
  67. static BOOL
  68. auth_chap_send_fail (conn_t * conn)
  69. {
  70. char str[16];
  71. str[0] = 0x01;
  72. str[1] = 0x01;
  73. str[2] = 0x00;
  74. str[3] = 0x01;
  75. str[4] = 0x01;
  76. return conn_sendData (conn, str, 5);
  77. }
  78. static BOOL
  79. auth_chap_send_ok (conn_t * conn)
  80. {
  81. char str[16];
  82. str[0] = 0x01;
  83. str[1] = 0x01;
  84. str[2] = 0x00;
  85. str[3] = 0x01;
  86. str[4] = 0x00;
  87. return conn_sendData (conn, str, 5);
  88. }
  89. /* This is an internal client library function. */
  90. int _an_socks5_hmacmd5_chap (const unsigned char *, int,
  91. const char *, unsigned char *);
  92. static BOOL
  93. auth_hmacmd5_chap (const unsigned char *challenge, int challen,
  94. const char *passwd, unsigned char **response, int *resplen)
  95. {
  96. unsigned char *respbuf;
  97. respbuf = (unsigned char *) malloc (20);
  98. if (respbuf == NULL)
  99. return FALSE;
  100. if (_an_socks5_hmacmd5_chap (challenge, challen,
  101. passwd, respbuf) == AN_ERROR_SUCCESS) {
  102. *response = respbuf;
  103. *resplen = 16;
  104. return TRUE;
  105. }
  106. free (respbuf);
  107. return FALSE;
  108. }
  109. BOOL
  110. auth_chap (conn_t * conn)
  111. {
  112. unsigned char version;
  113. unsigned char tmpch;
  114. unsigned char navas;
  115. unsigned char att[10];
  116. char challenge[100];
  117. char username[256];
  118. int thealgo;
  119. unsigned char *correctresp;
  120. unsigned char *gotresp;
  121. char *passwd;
  122. int resplen;
  123. BOOL authed;
  124. BOOL finished;
  125. BOOL sentChallenge;
  126. BOOL sendChallenge;
  127. int sendAlgo;
  128. int i, j;
  129. #ifdef WITH_DEBUG
  130. char szDebug[300];
  131. #endif
  132. finished = FALSE;
  133. authed = FALSE;
  134. gotresp = NULL;
  135. correctresp = NULL;
  136. passwd = NULL;
  137. sentChallenge = FALSE;
  138. thealgo = -1;
  139. strcpy (username, "");
  140. while (!finished) {
  141. sendChallenge = FALSE;
  142. sendAlgo = -1;
  143. if (!conn_getChar (conn, &version))
  144. return FALSE;
  145. if (version != 1)
  146. return FALSE;
  147. if (!conn_getChar (conn, &navas))
  148. return FALSE;
  149. for (i = 0; i < navas; i++) {
  150. if (!conn_getSlab (conn, (char *) &att, 2))
  151. return FALSE;
  152. /* Documented:
  153. * 0- status
  154. * 1- Text-message
  155. * 2- User-identity
  156. * 3- Challenge
  157. * 4- Response
  158. * 5- Charset
  159. * 16-Identifier
  160. * 17-Algorithms
  161. */
  162. #ifdef WITH_DEBUG
  163. sprintf (szDebug, "recved att %x data length %i", att[0], att[1]);
  164. DEBUG_LOG (szDebug);
  165. #endif
  166. switch (att[0]) {
  167. case 2:
  168. if (!conn_getSlab (conn, username, att[1]))
  169. goto barfed;
  170. #ifdef WITH_DEBUG
  171. sprintf (szDebug, "Set username to %s", username);
  172. DEBUG_LOG (szDebug);
  173. #endif
  174. if (!sentChallenge)
  175. sendChallenge = TRUE;
  176. break;
  177. case 4:
  178. gotresp = (unsigned char *) malloc (att[1] + 1);
  179. if (gotresp == NULL) {
  180. auth_chap_send_fail (conn);
  181. goto barfed;
  182. }
  183. if (!conn_getSlab (conn, (char *) gotresp, att[1])) {
  184. auth_chap_send_fail (conn);
  185. goto barfed;
  186. }
  187. if (thealgo < 0) {
  188. auth_chap_send_fail (conn);
  189. goto barfed;
  190. }
  191. if (!auth_getPasswordByUsername
  192. (conn->conf, username, &passwd)) {
  193. auth_chap_send_fail (conn);
  194. goto barfed;
  195. }
  196. switch (thealgo) {
  197. case 0x85: /* HMAC-MD5 */
  198. if (auth_hmacmd5_chap
  199. ((unsigned char *) challenge, 64, passwd,
  200. &correctresp, &resplen) == FALSE) {
  201. auth_chap_send_fail (conn);
  202. goto barfed;
  203. }
  204. break;
  205. default:
  206. auth_chap_send_fail (conn);
  207. goto barfed;
  208. break;
  209. }
  210. if (resplen != att[1]) {
  211. /* If the lengths differ, so do the responses */
  212. auth_chap_send_fail (conn);
  213. goto barfed;
  214. }
  215. if (memcmp (correctresp, gotresp, resplen) == 0) {
  216. auth_chap_send_ok (conn);
  217. conn_setUser (conn, username);
  218. conn_setPass (conn, passwd);
  219. conn->authsrc = AUTH_CONFIG;
  220. authed = TRUE;
  221. goto barfed;
  222. } else {
  223. auth_chap_send_fail (conn);
  224. goto barfed;
  225. }
  226. break;
  227. case 0x11:
  228. for (j = 0; j < att[1]; j++) {
  229. if (!conn_getChar (conn, &tmpch))
  230. goto barfed;
  231. if (sendAlgo < 0) {
  232. if (tmpch == 0x85)
  233. sendAlgo = tmpch;
  234. }
  235. }
  236. if (sendAlgo < 0)
  237. sendAlgo = -2;
  238. if (!sentChallenge)
  239. sendChallenge = TRUE;
  240. break;
  241. }
  242. }
  243. if (sendAlgo == -2) {
  244. auth_chap_send_fail (conn);
  245. goto barfed;
  246. }
  247. att[0] = 0x01;
  248. att[1] = 0x00;
  249. if (sendChallenge)
  250. att[1]++;
  251. if (sendAlgo >= 0)
  252. att[1]++;
  253. if (!conn_sendData (conn, (char *) att, 2))
  254. goto barfed;
  255. if (sendAlgo >= 0) {
  256. att[0] = 0x11;
  257. att[1] = 0x01;
  258. att[2] = sendAlgo;
  259. if (!conn_sendData (conn, (char *) att, 3))
  260. goto barfed;
  261. thealgo = sendAlgo;
  262. }
  263. if (sendChallenge) {
  264. auth_chap_gen_challenge (challenge, 64);
  265. att[0] = 0x03;
  266. att[1] = 0x40;
  267. if (!conn_sendData (conn, (char *) att, 2))
  268. goto barfed;
  269. if (!conn_sendData (conn, (char *) challenge, 64))
  270. goto barfed;
  271. }
  272. }
  273. barfed:
  274. if (gotresp != NULL)
  275. free (gotresp);
  276. if (correctresp != NULL)
  277. free (correctresp);
  278. if (passwd != NULL)
  279. free (passwd);
  280. #ifdef WITH_DEBUG
  281. if (authed) {
  282. DEBUG_LOG ("authenticated successfully");
  283. } else {
  284. DEBUG_LOG ("failed authentication");
  285. }
  286. #endif
  287. return authed;
  288. }
  289. /* TODO: Implement win32 native user authentication */
  290. #ifndef _WIN32_
  291. static BOOL
  292. auth_local (const char *username, const char *passwd)
  293. {
  294. char csalt[12];
  295. char *realpasswd;
  296. char pwhash[50];
  297. BOOL authed;
  298. #ifdef WITH_DEBUG
  299. char szDebug[300];
  300. #endif
  301. #ifdef HAVE_GETSPNAM
  302. struct spwd *shad_pw;
  303. #ifdef HAVE_GETSPNAM_R
  304. struct spwd realspwd;
  305. #endif
  306. #else
  307. #ifdef HAVE_GETPWNAM
  308. struct passwd *pw_pw;
  309. #ifdef HAVE_GETPWNAM_R
  310. struct passwd realpwd;
  311. #endif
  312. #endif
  313. #endif
  314. #if defined(HAVE_GETSPNAM_R)||(HAVE_GETPWNAM_R)
  315. char buf[1024];
  316. #endif
  317. #if (defined(HAVE_CRYPT_CRYPT_R)||defined(HAVE_CRYPT_R))&&(!defined(BROKEN_CRYPT_R))
  318. struct crypt_data cd;
  319. #endif
  320. #ifdef HAVE_GETSPNAM
  321. shad_pw = NULL;
  322. #endif
  323. authed = FALSE;
  324. realpasswd = NULL;
  325. #ifdef HAVE_GETSPNAM /* The system supports shadow password */
  326. #ifndef HAVE_GETSPNAM_R /* System has no reentrant shadow functions */
  327. os_mutex_lock (&getspnam_lock);
  328. shad_pw = getspnam (username);
  329. #else /* System has reentrant shadow functions */
  330. #ifdef BROKEN_GETSPNAM /* System has Solaris-style shadow functions */
  331. shad_pw = getspnam_r (username, &realspwd, buf, sizeof (buf));
  332. #else /* System has Linux-style shadow functions */
  333. getspnam_r (username, &realspwd, buf, sizeof (buf), &shad_pw);
  334. #endif /* BROKEN_GETSPNAM */
  335. #endif /* HAVE_GETSPNAM_R */
  336. if (shad_pw) {
  337. realpasswd = (char *) malloc (strlen (shad_pw->sp_pwdp) + 1);
  338. if (realpasswd)
  339. strcpy (realpasswd, shad_pw->sp_pwdp);
  340. }
  341. #ifndef HAVE_GETSPNAM_R /* No reentrant shadow functions */
  342. os_mutex_unlock (&getspnam_lock);
  343. #endif
  344. #else /* No shadow - try passwd */
  345. #ifdef HAVE_GETPWNAM /* Do we have passwd functions */
  346. #ifndef HAVE_GETPWNAM_R /* We have no reentrant passwd functions */
  347. os_mutex_lock (&getpwnam_lock);
  348. pw_pw = getpwnam (username);
  349. #else /* We have reentrant passwd functions */
  350. #ifdef BROKEN_GETPWNAM /* System has Solaris-style passwd functions */
  351. pw_pw = getpwnam_r (username, &realpwd, buf, sizeof (buf));
  352. #else /* System has Linux-style passwd functions */
  353. getpwnam_r (username, &realpwd, buf, sizeof (buf), &pw_pw);
  354. #endif /* BROKEN_GETPWNAM */
  355. #endif /* HAVE_GETPWNAM_R */
  356. if (pw_pw) {
  357. realpasswd = (char *) malloc (strlen (pw_pw->pw_passwd) + 1);
  358. if (realpasswd)
  359. strcpy (realpasswd, pw_pw->pw_passwd);
  360. }
  361. #ifndef HAVE_GETPWNAM_R /* No reentrant passwd functions */
  362. os_mutex_unlock (&getpwnam_lock);
  363. #endif /* HAVE_GETPWNAM_R */
  364. #endif /* HAVE_GETPWNAM */
  365. #endif /* HAVE_GETSPNAM */
  366. #ifdef WITH_DEBUG
  367. if (realpasswd) {
  368. sprintf (szDebug, "Found user, has hash %s", realpasswd);
  369. DEBUG_LOG (szDebug);
  370. } else
  371. DEBUG_LOG ("Username not found");
  372. #endif
  373. if (realpasswd) {
  374. csalt[0] = realpasswd[0];
  375. csalt[1] = realpasswd[1];
  376. csalt[2] = '\0';
  377. if (strcmp (csalt, "$1") == 0) {
  378. strncpy (csalt, realpasswd, 11);
  379. csalt[11] = '\0';
  380. }
  381. /* Apparently, crypt_r can't auth against non-MD5 passwds :( */
  382. #if (defined(HAVE_CRYPT_CRYPT_R)||defined(HAVE_CRYPT_R))&&(!defined(BROKEN_CRYPT_R))
  383. strcpy (pwhash, crypt_r (passwd, csalt, &cd));
  384. if (strcmp (pwhash, realpasswd) == 0) {
  385. authed = TRUE;
  386. } else {
  387. #ifdef WITH_DEBUG
  388. DEBUG_LOG ("Couldn't authenticate with crypt_r. Trying crypt.");
  389. #endif
  390. #endif
  391. os_mutex_lock (&crypt_lock);
  392. strcpy (pwhash, crypt (passwd, csalt));
  393. os_mutex_unlock (&crypt_lock);
  394. if (strcmp (pwhash, realpasswd) == 0) {
  395. authed = TRUE;
  396. }
  397. #if (defined(HAVE_CRYPT_CRYPT_R)||defined(HAVE_CRYPT_R))&&(!defined(BROKEN_CRYPT_R))
  398. }
  399. #endif
  400. }
  401. if (realpasswd)
  402. free (realpasswd);
  403. return authed;
  404. }
  405. #endif
  406. #ifdef _WIN32_
  407. #ifndef LOGON32_LOGON_NETWORK
  408. #define LOGON32_LOGON_NETWORK 3
  409. #endif
  410. #ifndef LOGON32_PROVIDER_DEFAULT
  411. #define LOGON32_PROVIDER_DEFAULT 0
  412. #endif
  413. typedef BOOL (*LogonUserProc) (LPTSTR, LPTSTR, LPTSTR, DWORD, DWORD, PHANDLE);
  414. static BOOL
  415. auth_local_win32 (const char *username, const char *passwd)
  416. {
  417. BOOL ret;
  418. HANDLE tok;
  419. HINSTANCE hDll;
  420. LogonUserProc lu;
  421. #ifdef WITH_DEBUG
  422. DWORD err;
  423. #endif
  424. hDll = LoadLibrary ("advapi32.dll");
  425. if (hDll == NULL) {
  426. #ifdef WITH_DEBUG
  427. DEBUG_LOG
  428. ("Local authentication cannot be supported on this build of Windows.");
  429. #endif
  430. return FALSE;
  431. }
  432. lu = (LogonUserProc) GetProcAddress (hDll, "LogonUserA");
  433. if (lu == NULL) {
  434. #ifdef WITH_DEBUG
  435. DEBUG_LOG
  436. ("Local authentication cannot be supported on this build of Windows.");
  437. #endif
  438. FreeLibrary (hDll);
  439. return FALSE;
  440. }
  441. ret =
  442. lu ((LPTSTR) username, NULL, (LPTSTR) passwd, LOGON32_LOGON_NETWORK,
  443. LOGON32_PROVIDER_DEFAULT, &tok);
  444. if (ret) {
  445. /* It worked? */
  446. CloseHandle (tok);
  447. FreeLibrary (hDll);
  448. return TRUE;
  449. }
  450. FreeLibrary (hDll);
  451. #ifdef WITH_DEBUG
  452. err = GetLastError ();
  453. if (err == ERROR_PRIVILEGE_NOT_HELD) {
  454. DEBUG_LOG
  455. ("Cannot locally authenticate without having 'Act as part of the operating system' user right");
  456. }
  457. #endif
  458. return FALSE;
  459. }
  460. #endif
  461. static BOOL
  462. auth_authUsernamePassword (conn_t * conn, const char *username,
  463. const char *passwd)
  464. {
  465. config_t *conf;
  466. char *correctpw;
  467. BOOL authed;
  468. conf = conn->conf;
  469. /* This is a placeholder for more auth mechanisms. */
  470. if (config_allowLocalUsers (conf)) {
  471. #ifndef _WIN32_
  472. if (auth_local (username, passwd)) {
  473. conn->authsrc = AUTH_LOCAL;
  474. return TRUE;
  475. }
  476. #else
  477. if (auth_local_win32 (username, passwd)) {
  478. conn->authsrc = AUTH_LOCAL;
  479. return TRUE;
  480. }
  481. #endif
  482. }
  483. authed = FALSE;
  484. if (auth_config_getpw (conf, username, &correctpw)) {
  485. if (strcmp (correctpw, passwd) == 0) {
  486. authed = TRUE;
  487. conn->authsrc = AUTH_CONFIG;
  488. }
  489. free (correctpw);
  490. }
  491. return authed;
  492. }
  493. BOOL
  494. auth_unpw (conn_t * conn)
  495. {
  496. unsigned char version;
  497. unsigned char length;
  498. char username[260];
  499. char passwd[260];
  500. char rep[3];
  501. BOOL authed;
  502. #ifdef WITH_DEBUG
  503. char szDebug[300];
  504. #endif
  505. authed = FALSE;
  506. if (!conn_getChar (conn, &version))
  507. return FALSE;
  508. if (version != 1)
  509. return FALSE;
  510. if (!conn_getChar (conn, &length))
  511. return FALSE;
  512. /* getSlab null terminates */
  513. if (!conn_getSlab (conn, username, length))
  514. goto barfed;
  515. if (!conn_getChar (conn, &length))
  516. goto barfed;
  517. if (!conn_getSlab (conn, passwd, length))
  518. goto barfed;
  519. authed = auth_authUsernamePassword (conn, username, passwd);
  520. barfed:
  521. rep[0] = 0x01;
  522. if (authed) {
  523. #ifdef WITH_DEBUG
  524. sprintf (szDebug, "User %s authenticated", username);
  525. #endif
  526. rep[1] = '\0';
  527. conn_setUser (conn, username);
  528. conn_setPass (conn, passwd);
  529. } else {
  530. #ifdef WITH_DEBUG
  531. sprintf (szDebug, "User %s NOT authenticated", username);
  532. #endif
  533. rep[1] = 0x01;
  534. }
  535. #ifdef WITH_DEBUG
  536. DEBUG_LOG (szDebug);
  537. #endif
  538. conn_sendData (conn, rep, 2);
  539. return authed;
  540. }