PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/nufw-2.4.3/src/clients/lib/internal.c

#
C | 781 lines | 570 code | 84 blank | 127 comment | 139 complexity | 591dd45115a562d0a773183d0a9e5a4a MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. ** Copyright 2004-2010 - EdenWall Technologies
  3. ** Written by Eric Leblond <regit@inl.fr>
  4. ** Vincent Deffontaines <vincent@inl.fr>
  5. ** Pierre Chifflier <chifflier@edenwall.com>
  6. ** INL http://www.inl.fr/
  7. **
  8. ** $Id$
  9. **
  10. ** This program is free software; you can redistribute it and/or modify
  11. ** it under the terms of the GNU General Public License as published by
  12. ** the Free Software Foundation, version 3 of the License.
  13. **
  14. ** This program is distributed in the hope that it will be useful,
  15. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ** GNU General Public License for more details.
  18. **
  19. ** You should have received a copy of the GNU General Public License
  20. ** along with this program; if not, write to the Free Software
  21. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. */
  23. #include "nufw_source.h"
  24. #include "libnuclient.h"
  25. #include "nuclient_plugins.h"
  26. #include "sending.h"
  27. #include "tcptable.h"
  28. #include <sasl/saslutil.h>
  29. #include <stdarg.h> /* va_list, va_start, ... */
  30. #include <langinfo.h>
  31. #include <proto.h>
  32. #include "proc.h"
  33. #include "security.h"
  34. #include "internal.h"
  35. #include <sys/utsname.h>
  36. #include <nussl.h>
  37. #include <nubase.h>
  38. char* nu_locale_charset;
  39. /**
  40. * \ingroup libnuclient
  41. * @{
  42. */
  43. /**
  44. * Display an error message, prefixed by "Fatal error: ", and then exit the
  45. * program. If filename is not NULL and line different than zero, also prefix
  46. * the message with them.
  47. *
  48. * Example: "checks.c:45:Fatal error: Message ..."
  49. */
  50. void do_panic(const char *filename, unsigned long line, const char *fmt,
  51. ...)
  52. {
  53. va_list args;
  54. va_start(args, fmt);
  55. printf("\n");
  56. if (filename != NULL && line != 0) {
  57. printf("%s:%lu:", filename, line);
  58. }
  59. printf("Fatal error: ");
  60. vprintf(fmt, args);
  61. printf("\n");
  62. fflush(stdout);
  63. exit(EXIT_FAILURE);
  64. va_end(args);
  65. }
  66. static int samp_send(nuauth_session_t* session, const char *buffer,
  67. unsigned length, nuclient_error_t * err)
  68. {
  69. char *buf;
  70. unsigned len, alloclen;
  71. int result;
  72. /* prefix ("C: ") + base64 length + 1 nul byte */
  73. alloclen = 3 + ((length+2)/3)*4 + 1;
  74. buf = malloc(alloclen);
  75. if (buf == NULL) {
  76. SET_ERROR(err, INTERNAL_ERROR, MEMORY_ERR);
  77. return 0;
  78. }
  79. result = sasl_encode64(buffer, length, buf + 3, alloclen - 3, &len);
  80. if (result != SASL_OK) {
  81. SET_ERROR(err, SASL_ERROR, result);
  82. free(buf);
  83. return 0;
  84. }
  85. memcpy(buf, "C: ", 3);
  86. result = nussl_write(session->nussl, buf, len + 3);
  87. if (result < 0) {
  88. SET_ERROR(err, NUSSL_ERR, result);
  89. free(buf);
  90. return 0;
  91. }
  92. free(buf);
  93. return 1;
  94. }
  95. /* XXX: Move this fuction into nussl */
  96. static unsigned samp_recv(nuauth_session_t* session, char *buf, int bufsize,
  97. nuclient_error_t * err)
  98. {
  99. unsigned len;
  100. int result;
  101. int tls_len;
  102. tls_len = nussl_read(session->nussl, buf, bufsize);
  103. if (tls_len <= 0) {
  104. log_printf(DEBUG_LEVEL_CRITICAL, "ERROR nussl_read returned %d (requested %d bytes)", tls_len, bufsize);
  105. SET_ERROR(err, NUSSL_ERR, tls_len);
  106. return 0;
  107. }
  108. result = sasl_decode64(buf + 3, (unsigned) strlen(buf + 3), buf,
  109. bufsize, &len);
  110. if (result != SASL_OK) {
  111. log_printf(DEBUG_LEVEL_CRITICAL, "ERROR sasl_decode64 returned %d", result);
  112. SET_ERROR(err, SASL_ERROR, result);
  113. return 0;
  114. }
  115. buf[len] = '\0';
  116. return len;
  117. }
  118. int mysasl_negotiate(nuauth_session_t * session, sasl_conn_t * conn,
  119. nuclient_error_t * err)
  120. {
  121. char buf[8192];
  122. const char *data;
  123. const char *mechlist = session->sasl_mechlist;
  124. const char *chosenmech;
  125. unsigned len;
  126. int result;
  127. int retry_auth = 1;
  128. /* gnutls_session session = session->tls; */
  129. memset(buf, 0, sizeof buf);
  130. /* get the capability list */
  131. len = samp_recv(session, buf, 8192, err);
  132. if (len == 0) {
  133. return SASL_FAIL;
  134. }
  135. if (mechlist == NULL)
  136. mechlist = buf;
  137. while (retry_auth > 0) {
  138. retry_auth--;
  139. if (session->verbose) {
  140. log_printf(DEBUG_LEVEL_DEBUG, "Server mechanisms %s", buf);
  141. log_printf(DEBUG_LEVEL_DEBUG, "Client mechanisms %s", mechlist);
  142. }
  143. result = sasl_client_start(conn,
  144. mechlist, NULL, &data, &len, &chosenmech);
  145. if (result == -1) {
  146. char * smech = strcasestr(mechlist, chosenmech);
  147. int strclen = strlen(chosenmech);
  148. /* remove chosenmech */
  149. if (smech == mechlist) {
  150. if (strcmp(mechlist, chosenmech) == 0) {
  151. break;
  152. }
  153. /* need only to offset mechlist */
  154. mechlist += strclen + 1;
  155. } else {
  156. int i = 0;
  157. /* comma need to be suppressed */
  158. smech--;
  159. /* copy string with offset */
  160. while (smech[i + strclen + 1]) {
  161. smech[i] = smech[i + strclen + 1];
  162. i++;
  163. }
  164. /* nullify end of string */
  165. smech[i] = 0;
  166. }
  167. /* try again with updated mechlist */
  168. log_printf(DEBUG_LEVEL_WARNING, "SASL negotiation with mechanism %s failed, retrying with %s",
  169. chosenmech,
  170. mechlist);
  171. retry_auth = 1;
  172. }
  173. }
  174. if (session->verbose) {
  175. log_printf(DEBUG_LEVEL_INFO, "Using mechanism %s", chosenmech);
  176. }
  177. if (result != SASL_OK && result != SASL_CONTINUE) {
  178. if (session->verbose) {
  179. log_printf(DEBUG_LEVEL_CRITICAL, "Error starting SASL negotiation");
  180. log_printf(DEBUG_LEVEL_CRITICAL, "\n%s\n", sasl_errdetail(conn));
  181. }
  182. SET_ERROR(err, SASL_ERROR, result);
  183. return SASL_FAIL;
  184. }
  185. strcpy(buf, chosenmech);
  186. if (data) {
  187. if (8192 - strlen(buf) - 1 < len) {
  188. return SASL_FAIL;
  189. }
  190. memcpy(buf + strlen(buf) + 1, data, len);
  191. len += (unsigned) strlen(buf) + 1;
  192. data = NULL;
  193. } else {
  194. len = (unsigned) strlen(buf);
  195. }
  196. if (!samp_send(session, buf, len, err)) {
  197. return SASL_FAIL;
  198. }
  199. while (result == SASL_CONTINUE) {
  200. if (session->verbose) {
  201. log_printf(DEBUG_LEVEL_DEBUG, "Waiting for server reply...");
  202. }
  203. memset(buf, 0, sizeof(buf));
  204. len = samp_recv(session, buf, sizeof(buf), err);
  205. if (len <= 0) {
  206. log_printf(DEBUG_LEVEL_CRITICAL, "server problem, recv fail...");
  207. return SASL_FAIL;
  208. }
  209. result =
  210. sasl_client_step(conn, buf, len, NULL, &data, &len);
  211. if (result != SASL_OK && result != SASL_CONTINUE) {
  212. if (session->verbose)
  213. log_printf(DEBUG_LEVEL_DEBUG, "Performing SASL negotiation");
  214. SET_ERROR(err, SASL_ERROR, result);
  215. }
  216. if (data && len) {
  217. if (session->verbose)
  218. puts("Sending response...\n");
  219. if (!samp_send(session, data, len, err)) {
  220. return SASL_FAIL;
  221. }
  222. } else if (result != SASL_OK) {
  223. if (!samp_send(session, "", 0, err)) {
  224. return SASL_FAIL;
  225. }
  226. }
  227. }
  228. len = samp_recv(session, buf, 42, err);
  229. if (buf[0] != 'Y') {
  230. result = SASL_BADAUTH;
  231. SET_ERROR(err, SASL_ERROR, SASL_BADAUTH);
  232. }
  233. if (result != SASL_OK) {
  234. if (session->verbose)
  235. puts("Authentication failed...");
  236. return SASL_FAIL;
  237. } else {
  238. if (session->verbose)
  239. puts("Authentication started...");
  240. }
  241. return SASL_OK;
  242. }
  243. int add_packet_to_send(nuauth_session_t * session, conn_t ** auth,
  244. int *count_p, conn_t * bucket)
  245. {
  246. int count = *count_p;
  247. if (count < CONN_MAX - 1) {
  248. auth[count] = bucket;
  249. (*count_p)++;
  250. } else {
  251. int i;
  252. auth[count] = bucket;
  253. if (send_user_pckt(session, auth) != 1) {
  254. /* error sending */
  255. #if DEBUG
  256. log_printf(DEBUG_LEVEL_CRITICAL, "error when sending");
  257. #endif
  258. return -1;
  259. }
  260. for (i = 0; i < CONN_MAX; i++) {
  261. auth[i] = NULL;
  262. }
  263. *count_p = 0;
  264. }
  265. return 1;
  266. }
  267. /**
  268. * \brief Compare connection tables and send packets
  269. *
  270. * Compare the `old' and `new' tables, sending packet to nuauth
  271. * if differences are found.
  272. *
  273. * \return -1 if error (then disconnect is needed) or the number of
  274. * authenticated packets if it has succeeded
  275. */
  276. int compare(nuauth_session_t * session, conntable_t * old, conntable_t * new,
  277. nuclient_error_t * err)
  278. {
  279. int i;
  280. int count = 0;
  281. conn_t *auth[CONN_MAX];
  282. int nb_packets = 0;
  283. assert(old != NULL);
  284. assert(new != NULL);
  285. for (i = 0; i < CONNTABLE_BUCKETS; i++) {
  286. conn_t *bucket;
  287. conn_t *same_bucket;
  288. bucket = new->buckets[i];
  289. while (bucket != NULL) {
  290. same_bucket = tcptable_find(old, bucket);
  291. if (same_bucket == NULL) {
  292. #if DEBUG
  293. log_printf(DEBUG_LEVEL_DEBUG, "sending new");
  294. #endif
  295. #ifdef LINUX
  296. prg_cache_load();
  297. #endif
  298. if (add_packet_to_send
  299. (session, auth, &count,
  300. bucket) == -1) {
  301. /* problem when sending we exit */
  302. return -1;
  303. }
  304. plugin_emit_event(NUCLIENT_EVENT_NEW_CONNECTION, session, (char *)bucket);
  305. nb_packets++;
  306. } else {
  307. /* compare values of retransmit */
  308. if (bucket->retransmit >
  309. same_bucket->retransmit) {
  310. #if DEBUG
  311. log_printf(DEBUG_LEVEL_DEBUG, "sending retransmit");
  312. #endif
  313. #ifdef LINUX
  314. prg_cache_load();
  315. #endif
  316. if (add_packet_to_send
  317. (session, auth, &count,
  318. bucket) == -1) {
  319. /* problem when sending we exit */
  320. return -1;
  321. }
  322. plugin_emit_event(NUCLIENT_EVENT_RETRANSMIT_CONNECTION, session, (char *)bucket);
  323. nb_packets++;
  324. }
  325. /* solve timeout issue on UDP */
  326. if (bucket->protocol == IPPROTO_UDP) {
  327. /* send an auth packet if netfilter timeout may have been reached */
  328. if (same_bucket->createtime <
  329. time(NULL) - UDP_TIMEOUT) {
  330. #if DEBUG
  331. log_printf(DEBUG_LEVEL_DEBUG,
  332. "working on timeout issue");
  333. #endif
  334. #ifdef LINUX
  335. prg_cache_load();
  336. #endif
  337. if (add_packet_to_send
  338. (session, auth, &count,
  339. bucket) == -1) {
  340. return -1;
  341. }
  342. nb_packets++;
  343. } else {
  344. bucket->createtime =
  345. same_bucket->
  346. createtime;
  347. }
  348. }
  349. }
  350. bucket = bucket->next;
  351. }
  352. }
  353. if (count > 0) {
  354. if (count < CONN_MAX) {
  355. auth[count] = NULL;
  356. }
  357. if (send_user_pckt(session, auth) != 1) {
  358. /* error sending */
  359. return -1;
  360. }
  361. }
  362. return nb_packets;
  363. }
  364. /**
  365. * Create the operating system packet and send it to nuauth.
  366. * Packet is in format ::nuv2_authfield.
  367. *
  368. * \param session Pointer to client session
  369. * \param err Pointer to a nuclient_error_t: which contains the error
  370. */
  371. int send_os(nuauth_session_t * session, nuclient_error_t * err)
  372. {
  373. /* announce our OS */
  374. struct utsname info;
  375. char oses[256];
  376. char buf[1024];
  377. char *enc_oses = buf + sizeof(struct nu_authfield);
  378. struct nu_authfield *osfield = (struct nu_authfield *) buf;
  379. unsigned stringlen;
  380. unsigned actuallen;
  381. int ret;
  382. /* read OS informations */
  383. uname(&info);
  384. /* encode OS informations in base64 */
  385. stringlen = strlen(info.sysname) + 1
  386. + strlen(info.release) + 1 + strlen(info.version) + 1;
  387. (void) secure_snprintf(oses, stringlen,
  388. "%s;%s;%s",
  389. info.sysname, info.release, info.version);
  390. if (sasl_encode64(oses, strlen(oses), enc_oses, 4 * stringlen,
  391. &actuallen) == SASL_BUFOVER) {
  392. SET_ERROR(err, SASL_ERROR, SASL_BUFOVER);
  393. /* TODO set explicit string message */
  394. return 0;
  395. }
  396. /* build packet header */
  397. osfield->type = OS_FIELD;
  398. osfield->option = OS_SRV;
  399. osfield->length = sizeof(struct nu_authfield) + actuallen;
  400. /* add packet body */
  401. osfield->length = htons(osfield->length);
  402. /* Send OS field over network */
  403. ret = nussl_write(session->nussl, buf, ntohs(osfield->length));
  404. if (ret < 0) {
  405. if (session->verbose)
  406. log_printf(DEBUG_LEVEL_CRITICAL, "Error sending tls data: ...");
  407. SET_ERROR(err, NUSSL_ERR, ret);
  408. return 0;
  409. }
  410. return 1;
  411. }
  412. /**
  413. * Create the client information packet and send it to nuauth.
  414. * Packet is in format ::nuv2_authfield.
  415. *
  416. * \param session Pointer to client session
  417. * \param err Pointer to a nuclient_error_t: which contains the error
  418. */
  419. int send_client(nuauth_session_t * session, nuclient_error_t * err)
  420. {
  421. char version[256];
  422. char buf[1024];
  423. struct nu_authfield *vfield = (struct nu_authfield *) buf;
  424. char *enc_version = buf + sizeof(struct nu_authfield);
  425. unsigned stringlen = 256;
  426. unsigned actuallen;
  427. int ret;
  428. (void) secure_snprintf(version, stringlen,
  429. "%s;%s",
  430. session->client_name, session->client_version);
  431. if (sasl_encode64(version, strlen(version), enc_version, 4 * stringlen,
  432. &actuallen) == SASL_BUFOVER) {
  433. SET_ERROR(err, SASL_ERROR, SASL_BUFOVER);
  434. /* TODO set explicit string message */
  435. return 0;
  436. }
  437. /* build packet header */
  438. vfield->type = VERSION_FIELD;
  439. vfield->option = CLIENT_SRV;
  440. vfield->length = sizeof(struct nu_authfield) + actuallen;
  441. /* add packet body */
  442. vfield->length = htons(vfield->length);
  443. /* Send Client version field over network */
  444. ret = nussl_write(session->nussl, buf, ntohs(vfield->length));
  445. if (ret < 0) {
  446. if (session->verbose)
  447. log_printf(DEBUG_LEVEL_CRITICAL, "Error sending tls data: ...");
  448. SET_ERROR(err, NUSSL_ERR, ret);
  449. return 0;
  450. }
  451. return 1;
  452. }
  453. /**
  454. * Create the client information packet and send it to nuauth.
  455. * Packet is in format ::nuv2_authfield.
  456. *
  457. * \param session Pointer to client session
  458. * \param err Pointer to a nuclient_error_t: which contains the error
  459. */
  460. int send_capa(nuauth_session_t * session, nuclient_error_t * err)
  461. {
  462. char buf[1024];
  463. struct nu_authfield *vfield = (struct nu_authfield *) buf;
  464. char *enc_capa = buf + sizeof(struct nu_authfield);
  465. unsigned stringlen = sizeof(nu_capabilities);
  466. unsigned actuallen;
  467. char *capa;
  468. int ret;
  469. if (session->nu_capabilities[0])
  470. capa = session->nu_capabilities;
  471. else
  472. capa = nu_capabilities;
  473. if (sasl_encode64(capa, strlen(capa), enc_capa, 4 * stringlen,
  474. &actuallen) == SASL_BUFOVER) {
  475. SET_ERROR(err, SASL_ERROR, SASL_BUFOVER);
  476. /* TODO set explicit string message */
  477. return 0;
  478. }
  479. /* build packet header */
  480. vfield->type = CAPA_FIELD;
  481. vfield->option = CLIENT_SRV;
  482. vfield->length = sizeof(struct nu_authfield) + actuallen;
  483. /* add packet body */
  484. vfield->length = htons(vfield->length);
  485. /* Send capabilities field over network */
  486. ret = nussl_write(session->nussl, buf, ntohs(vfield->length));
  487. if (ret < 0) {
  488. if (session->verbose)
  489. log_printf(DEBUG_LEVEL_CRITICAL, "Error sending tls data: ...");
  490. SET_ERROR(err, NUSSL_ERR, ret);
  491. return 0;
  492. }
  493. return 1;
  494. }
  495. /**
  496. * SASL callback used to get password
  497. *
  498. * \return SASL_OK if ok, EXIT_FAILURE on error
  499. */
  500. static int nu_get_usersecret(sasl_conn_t * conn __attribute__ ((unused)),
  501. void *context __attribute__ ((unused)), int id,
  502. sasl_secret_t ** psecret)
  503. {
  504. size_t len;
  505. nuauth_session_t *session = (nuauth_session_t *) context;
  506. if (id != SASL_CB_PASS) {
  507. if (session->verbose)
  508. log_printf(DEBUG_LEVEL_CRITICAL, "getsecret not looking for pass");
  509. return SASL_BADPARAM;
  510. }
  511. if ((session->password == NULL) && session->passwd_callback) {
  512. #if USE_UTF8
  513. char *utf8pass;
  514. #endif
  515. char *givenpass=session->passwd_callback();
  516. if (!givenpass){
  517. return SASL_FAIL;
  518. }
  519. #if USE_UTF8
  520. utf8pass = nu_client_to_utf8(givenpass, nu_locale_charset);
  521. free(givenpass);
  522. givenpass = utf8pass;
  523. if (!givenpass){
  524. return SASL_FAIL;
  525. }
  526. #endif
  527. session->password = givenpass;
  528. }
  529. if (!psecret)
  530. return SASL_BADPARAM;
  531. len = strlen(session->password);
  532. *psecret =
  533. (sasl_secret_t *) calloc(sizeof(sasl_secret_t) + len + 1,
  534. sizeof(char));
  535. (*psecret)->len = len;
  536. SECURE_STRNCPY((char *) (*psecret)->data, session->password,
  537. len + 1);
  538. return SASL_OK;
  539. }
  540. static int nu_get_userdata(void *context __attribute__ ((unused)),
  541. int id, const char **result, unsigned *len)
  542. {
  543. nuauth_session_t *session = (nuauth_session_t *) context;
  544. /* paranoia check */
  545. if (!result)
  546. return SASL_BADPARAM;
  547. switch (id) {
  548. case SASL_CB_USER:
  549. case SASL_CB_AUTHNAME:
  550. if ((session->username == NULL) && session->username_callback) {
  551. #if USE_UTF8
  552. char *utf8name;
  553. #endif
  554. char *givenuser=session->username_callback();
  555. #if USE_UTF8
  556. utf8name = nu_client_to_utf8(givenuser, nu_locale_charset);
  557. free(givenuser);
  558. givenuser = utf8name;
  559. if (givenuser == NULL){
  560. return SASL_FAIL;
  561. }
  562. #endif
  563. session->username = givenuser;
  564. }
  565. *result = session->username;
  566. break;
  567. default:
  568. return SASL_BADPARAM;
  569. }
  570. if (len)
  571. *len = strlen(*result);
  572. return SASL_OK;
  573. }
  574. /**
  575. * Initialize SASL: create an client, set properties
  576. * and then call mysasl_negotiate()
  577. *
  578. * \param session Pointer to client session
  579. * \param hostname Name (FQDN) of the Nuauth server
  580. * \param err Pointer to a nuclient_error_t: which contains the error
  581. */
  582. int init_sasl(nuauth_session_t * session, const char *hostname, nuclient_error_t * err)
  583. {
  584. int ret;
  585. sasl_conn_t *conn;
  586. sasl_ssf_t extssf = 0;
  587. char * krb5_service = NULL;
  588. const char * server_fqdn = hostname;
  589. sasl_security_properties_t secprops;
  590. char buffer[12];
  591. /* SASL time */
  592. sasl_callback_t callbacks[] = {
  593. {SASL_CB_USER, &nu_get_userdata, session},
  594. {SASL_CB_AUTHNAME, &nu_get_userdata, session},
  595. {SASL_CB_PASS, &nu_get_usersecret, session},
  596. {SASL_CB_LIST_END, NULL, NULL}
  597. };
  598. ret = nussl_write(session->nussl, "PROTO 6", strlen("PROTO 6"));
  599. if (ret < 0) {
  600. SET_ERROR(err, NUSSL_ERR, ret);
  601. return 0;
  602. }
  603. /* wait of "OK" from server, an other chain will be a failure
  604. * because we can not yet downgrade our protocol */
  605. ret = nussl_read(session->nussl, buffer, sizeof(buffer));
  606. if (ret <= 0) {
  607. log_printf(DEBUG_LEVEL_CRITICAL,
  608. "nussl_read() failed: %s",
  609. nussl_get_error(session->nussl));
  610. SET_ERROR(err, NUSSL_ERR, ret);
  611. return 0;
  612. }
  613. if (strncmp("OK", buffer, 2)) {
  614. log_printf(DEBUG_LEVEL_CRITICAL, "received: \"%s\"", buffer);
  615. SET_ERROR(err, INTERNAL_ERROR, PROTO_ERR);
  616. return 0;
  617. }
  618. krb5_service = session->krb5_service;
  619. if (krb5_service == NULL)
  620. krb5_service = DEFAULT_KRB5_REALM;
  621. /* client new connection */
  622. ret = sasl_client_new(krb5_service, server_fqdn, NULL, NULL, callbacks, 0, &conn);
  623. if (ret != SASL_OK) {
  624. if (session->verbose)
  625. log_printf(DEBUG_LEVEL_CRITICAL, "Failed allocating connection state");
  626. errno = EAGAIN;
  627. SET_ERROR(err, SASL_ERROR, ret);
  628. return 0;
  629. }
  630. if (! session->username){
  631. /* set username taken from console */
  632. if (session->username_callback){
  633. session->username = session->username_callback();
  634. } else {
  635. if (session->verbose)
  636. log_printf(DEBUG_LEVEL_CRITICAL, "Can't call username callback");
  637. }
  638. }
  639. secprops.min_ssf = 0;
  640. secprops.max_ssf = UINT_MAX;
  641. secprops.property_names = NULL;
  642. secprops.property_values = NULL;
  643. secprops.security_flags = SASL_SEC_NOANONYMOUS; /* as appropriate */
  644. secprops.maxbufsize = 65536;
  645. sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
  646. sasl_setprop(conn, SASL_SSF_EXTERNAL, &extssf);
  647. ret = sasl_setprop(conn, SASL_AUTH_EXTERNAL, session->username);
  648. if (ret != SASL_OK) {
  649. errno = EACCES;
  650. SET_ERROR(err, SASL_ERROR, ret);
  651. return 0;
  652. }
  653. ret = mysasl_negotiate(session, conn, err);
  654. if (ret != SASL_OK) {
  655. errno = EACCES;
  656. /* SET_ERROR(err, SASL_ERROR, ret); */
  657. return 0;
  658. }
  659. sasl_dispose(&conn);
  660. return 1;
  661. }
  662. /**
  663. * Make a copy in a string in a secure memory buffer, ie. buffer never moved
  664. * to swap (hard drive). Use secure_str_free() to free the memory when you
  665. * don't need the string anymore.
  666. *
  667. * If USE_GCRYPT_MALLOC_SECURE compilation option in not set,
  668. * strdup() is used.
  669. *
  670. * \return Copy of the string, or NULL on error.
  671. */
  672. char *secure_str_copy(const char *orig)
  673. {
  674. #ifdef USE_GCRYPT_MALLOC_SECURE
  675. size_t len = strlen(orig);
  676. char *new = gcry_calloc_secure(len + 1, sizeof(char));
  677. if (new != NULL) {
  678. SECURE_STRNCPY(new, orig, len + 1);
  679. }
  680. return new;
  681. #else
  682. return strdup(orig);
  683. #endif
  684. }
  685. void ask_session_end(nuauth_session_t * session)
  686. {
  687. /* sanity checks */
  688. if (session == NULL) {
  689. return;
  690. }
  691. if (session->nussl) {
  692. nussl_session_destroy(session->nussl);
  693. session->nussl = NULL;
  694. }
  695. session->connected = 0;
  696. }
  697. /** @} */