plugin_common.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. /* Generic SASL plugin utility functions
  2. * Rob Siemborski
  3. */
  4. /*
  5. * Copyright (c) 1998-2016 Carnegie Mellon University. All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The name "Carnegie Mellon University" must not be used to
  20. * endorse or promote products derived from this software without
  21. * prior written permission. For permission or any other legal
  22. * details, please contact
  23. * Carnegie Mellon University
  24. * Center for Technology Transfer and Enterprise Creation
  25. * 4615 Forbes Avenue
  26. * Suite 302
  27. * Pittsburgh, PA 15213
  28. * (412) 268-7393, fax: (412) 268-7395
  29. * innovation@andrew.cmu.edu
  30. *
  31. * 4. Redistributions of any form whatsoever must retain the following
  32. * acknowledgment:
  33. * "This product includes software developed by Computing Services
  34. * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
  35. *
  36. * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
  37. * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  38. * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
  39. * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  40. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  41. * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  42. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  43. */
  44. #include <config.h>
  45. #ifndef macintosh
  46. #ifdef WIN32
  47. # include <winsock2.h>
  48. # include <versionhelpers.h>
  49. #else
  50. # include <sys/socket.h>
  51. # include <netinet/in.h>
  52. # include <arpa/inet.h>
  53. # include <netdb.h>
  54. # include <sys/utsname.h>
  55. #endif /* WIN32 */
  56. #endif /* macintosh */
  57. #ifdef HAVE_UNISTD_H
  58. #include <unistd.h>
  59. #endif
  60. #include <fcntl.h>
  61. #include <sasl.h>
  62. #include <saslutil.h>
  63. #include <saslplug.h>
  64. #include <errno.h>
  65. #include <ctype.h>
  66. #include <stdio.h>
  67. #ifdef HAVE_INTTYPES_H
  68. #include <inttypes.h>
  69. #endif
  70. #include "plugin_common.h"
  71. /* translate IPv4 mapped IPv6 address to IPv4 address */
  72. static void sockaddr_unmapped(
  73. #ifdef IN6_IS_ADDR_V4MAPPED
  74. struct sockaddr *sa, socklen_t *len
  75. #else
  76. struct sockaddr *sa __attribute__((unused)),
  77. socklen_t *len __attribute__((unused))
  78. #endif
  79. )
  80. {
  81. #ifdef IN6_IS_ADDR_V4MAPPED
  82. struct sockaddr_in6 *sin6;
  83. struct sockaddr_in *sin4;
  84. uint32_t addr;
  85. int port;
  86. if (sa->sa_family != AF_INET6)
  87. return;
  88. sin6 = (struct sockaddr_in6 *)sa;
  89. if (!IN6_IS_ADDR_V4MAPPED((&sin6->sin6_addr)))
  90. return;
  91. sin4 = (struct sockaddr_in *)sa;
  92. #ifdef s6_addr32
  93. addr = *(uint32_t *)&sin6->sin6_addr.s6_addr32[3];
  94. #else
  95. memcpy(&addr, &sin6->sin6_addr.s6_addr[12], 4);
  96. #endif
  97. port = sin6->sin6_port;
  98. memset(sin4, 0, sizeof(struct sockaddr_in));
  99. sin4->sin_addr.s_addr = addr;
  100. sin4->sin_port = port;
  101. sin4->sin_family = AF_INET;
  102. #ifdef HAVE_SOCKADDR_SA_LEN
  103. sin4->sin_len = sizeof(struct sockaddr_in);
  104. #endif
  105. *len = sizeof(struct sockaddr_in);
  106. #else
  107. return;
  108. #endif
  109. }
  110. int _plug_ipfromstring(const sasl_utils_t *utils, const char *addr,
  111. struct sockaddr *out, socklen_t outlen)
  112. {
  113. int i, j;
  114. socklen_t len;
  115. struct sockaddr_storage ss;
  116. struct addrinfo hints, *ai = NULL;
  117. char hbuf[NI_MAXHOST];
  118. if(!utils || !addr || !out) {
  119. if(utils) PARAMERROR( utils );
  120. return SASL_BADPARAM;
  121. }
  122. /* Parse the address */
  123. for (i = 0; addr[i] != '\0' && addr[i] != ';'; i++) {
  124. if (i + 1 >= NI_MAXHOST) {
  125. if(utils) PARAMERROR( utils );
  126. return SASL_BADPARAM;
  127. }
  128. hbuf[i] = addr[i];
  129. }
  130. hbuf[i] = '\0';
  131. if (addr[i] == ';')
  132. i++;
  133. /* XXX/FIXME: Do we need this check? */
  134. for (j = i; addr[j] != '\0'; j++)
  135. if (!isdigit((int)(addr[j]))) {
  136. PARAMERROR( utils );
  137. return SASL_BADPARAM;
  138. }
  139. memset(&hints, 0, sizeof(hints));
  140. hints.ai_family = PF_UNSPEC;
  141. hints.ai_socktype = SOCK_STREAM;
  142. hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
  143. if (getaddrinfo(hbuf, &addr[i], &hints, &ai) != 0) {
  144. PARAMERROR( utils );
  145. return SASL_BADPARAM;
  146. }
  147. len = (socklen_t) ai->ai_addrlen;
  148. memcpy(&ss, ai->ai_addr, len);
  149. freeaddrinfo(ai);
  150. sockaddr_unmapped((struct sockaddr *)&ss, &len);
  151. if (outlen < len) {
  152. PARAMERROR( utils );
  153. return SASL_BUFOVER;
  154. }
  155. memcpy(out, &ss, len);
  156. return SASL_OK;
  157. }
  158. int _plug_iovec_to_buf(const sasl_utils_t *utils, const struct iovec *vec,
  159. unsigned numiov, buffer_info_t **output)
  160. {
  161. unsigned i;
  162. int ret;
  163. buffer_info_t *out;
  164. char *pos;
  165. if(!utils || !vec || !output) {
  166. if(utils) PARAMERROR( utils );
  167. return SASL_BADPARAM;
  168. }
  169. if(!(*output)) {
  170. *output = utils->malloc(sizeof(buffer_info_t));
  171. if(!*output) {
  172. MEMERROR(utils);
  173. return SASL_NOMEM;
  174. }
  175. memset(*output,0,sizeof(buffer_info_t));
  176. }
  177. out = *output;
  178. out->curlen = 0;
  179. for(i=0; i<numiov; i++)
  180. out->curlen += vec[i].iov_len;
  181. ret = _plug_buf_alloc(utils, &out->data, &out->reallen, out->curlen);
  182. if(ret != SASL_OK) {
  183. MEMERROR(utils);
  184. return SASL_NOMEM;
  185. }
  186. memset(out->data, 0, out->reallen);
  187. pos = out->data;
  188. for(i=0; i<numiov; i++) {
  189. memcpy(pos, vec[i].iov_base, vec[i].iov_len);
  190. pos += vec[i].iov_len;
  191. }
  192. return SASL_OK;
  193. }
  194. /* Basically a conditional call to realloc(), if we need more */
  195. int _plug_buf_alloc(const sasl_utils_t *utils, char **rwbuf,
  196. unsigned *curlen, unsigned newlen)
  197. {
  198. if(!utils || !rwbuf || !curlen) {
  199. if (utils) PARAMERROR(utils);
  200. return SASL_BADPARAM;
  201. }
  202. if(!(*rwbuf)) {
  203. *rwbuf = utils->malloc(newlen);
  204. if (*rwbuf == NULL) {
  205. *curlen = 0;
  206. MEMERROR(utils);
  207. return SASL_NOMEM;
  208. }
  209. *curlen = newlen;
  210. } else if(*rwbuf && *curlen < newlen) {
  211. unsigned needed = 2*(*curlen);
  212. while(needed < newlen)
  213. needed *= 2;
  214. *rwbuf = utils->realloc(*rwbuf, needed);
  215. if (*rwbuf == NULL) {
  216. *curlen = 0;
  217. MEMERROR(utils);
  218. return SASL_NOMEM;
  219. }
  220. *curlen = needed;
  221. }
  222. return SASL_OK;
  223. }
  224. /* copy a string */
  225. int _plug_strdup(const sasl_utils_t * utils, const char *in,
  226. char **out, int *outlen)
  227. {
  228. size_t len = 0;
  229. if(!utils || !in || !out) {
  230. if(utils) PARAMERROR(utils);
  231. return SASL_BADPARAM;
  232. }
  233. len = strlen(in);
  234. *out = utils->malloc(len + 1);
  235. if (!*out) {
  236. MEMERROR(utils);
  237. return SASL_NOMEM;
  238. }
  239. strcpy((char *) *out, in);
  240. if (outlen)
  241. *outlen = (int) len;
  242. return SASL_OK;
  243. }
  244. void _plug_free_string(const sasl_utils_t *utils, char **str)
  245. {
  246. size_t len;
  247. if (!utils || !str || !(*str)) return;
  248. len = strlen(*str);
  249. utils->erasebuffer(*str, (unsigned int) len);
  250. utils->free(*str);
  251. *str=NULL;
  252. }
  253. void _plug_free_secret(const sasl_utils_t *utils, sasl_secret_t **secret)
  254. {
  255. if(!utils || !secret || !(*secret)) return;
  256. utils->erasebuffer((char *)(*secret)->data, (*secret)->len);
  257. utils->free(*secret);
  258. *secret = NULL;
  259. }
  260. /*
  261. * Trys to find the prompt with the lookingfor id in the prompt list
  262. * Returns it if found. NULL otherwise
  263. */
  264. sasl_interact_t *_plug_find_prompt(sasl_interact_t **promptlist,
  265. unsigned int lookingfor)
  266. {
  267. sasl_interact_t *prompt;
  268. if (promptlist && *promptlist) {
  269. for (prompt = *promptlist; prompt->id != SASL_CB_LIST_END; ++prompt) {
  270. if (prompt->id==lookingfor)
  271. return prompt;
  272. }
  273. }
  274. return NULL;
  275. }
  276. /*
  277. * Retrieve the simple string given by the callback id.
  278. */
  279. int _plug_get_simple(const sasl_utils_t *utils, unsigned int id, int required,
  280. const char **result, sasl_interact_t **prompt_need)
  281. {
  282. int ret = SASL_FAIL;
  283. sasl_getsimple_t *simple_cb;
  284. void *simple_context;
  285. sasl_interact_t *prompt;
  286. *result = NULL;
  287. /* see if we were given the result in the prompt */
  288. prompt = _plug_find_prompt(prompt_need, id);
  289. if (prompt != NULL) {
  290. /* We prompted, and got.*/
  291. if (required && !prompt->result) {
  292. SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_simple");
  293. return SASL_BADPARAM;
  294. }
  295. *result = prompt->result;
  296. return SASL_OK;
  297. }
  298. /* Try to get the callback... */
  299. ret = utils->getcallback(utils->conn, id, (sasl_callback_ft *)&simple_cb, &simple_context);
  300. if (ret == SASL_FAIL && !required)
  301. return SASL_OK;
  302. if (ret == SASL_OK && simple_cb) {
  303. ret = simple_cb(simple_context, id, result, NULL);
  304. if (ret != SASL_OK)
  305. return ret;
  306. if (required && !*result) {
  307. PARAMERROR(utils);
  308. return SASL_BADPARAM;
  309. }
  310. }
  311. return ret;
  312. }
  313. /*
  314. * Retrieve the user password.
  315. */
  316. int _plug_get_password(const sasl_utils_t *utils, sasl_secret_t **password,
  317. unsigned int *iscopy, sasl_interact_t **prompt_need)
  318. {
  319. int ret = SASL_FAIL;
  320. sasl_getsecret_t *pass_cb;
  321. void *pass_context;
  322. sasl_interact_t *prompt;
  323. *password = NULL;
  324. *iscopy = 0;
  325. /* see if we were given the password in the prompt */
  326. prompt = _plug_find_prompt(prompt_need, SASL_CB_PASS);
  327. if (prompt != NULL) {
  328. /* We prompted, and got.*/
  329. if (!prompt->result) {
  330. SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_password");
  331. return SASL_BADPARAM;
  332. }
  333. /* copy what we got into a secret_t */
  334. *password = (sasl_secret_t *) utils->malloc(sizeof(sasl_secret_t) +
  335. prompt->len + 1);
  336. if (!*password) {
  337. MEMERROR(utils);
  338. return SASL_NOMEM;
  339. }
  340. (*password)->len=prompt->len;
  341. memcpy((*password)->data, prompt->result, prompt->len);
  342. (*password)->data[(*password)->len]=0;
  343. *iscopy = 1;
  344. return SASL_OK;
  345. }
  346. /* Try to get the callback... */
  347. ret = utils->getcallback(utils->conn, SASL_CB_PASS,
  348. (sasl_callback_ft *)&pass_cb, &pass_context);
  349. if (ret == SASL_OK && pass_cb) {
  350. ret = pass_cb(utils->conn, pass_context, SASL_CB_PASS, password);
  351. if (ret != SASL_OK)
  352. return ret;
  353. if (!*password) {
  354. PARAMERROR(utils);
  355. return SASL_BADPARAM;
  356. }
  357. }
  358. return ret;
  359. }
  360. /*
  361. * Retrieve the string given by the challenge prompt id.
  362. */
  363. int _plug_challenge_prompt(const sasl_utils_t *utils, unsigned int id,
  364. const char *challenge, const char *promptstr,
  365. const char **result, sasl_interact_t **prompt_need)
  366. {
  367. int ret = SASL_FAIL;
  368. sasl_chalprompt_t *chalprompt_cb;
  369. void *chalprompt_context;
  370. sasl_interact_t *prompt;
  371. *result = NULL;
  372. /* see if we were given the password in the prompt */
  373. prompt = _plug_find_prompt(prompt_need, id);
  374. if (prompt != NULL) {
  375. /* We prompted, and got.*/
  376. if (!prompt->result) {
  377. SETERROR(utils, "Unexpectedly missing a prompt result in _plug_challenge_prompt");
  378. return SASL_BADPARAM;
  379. }
  380. *result = prompt->result;
  381. return SASL_OK;
  382. }
  383. /* Try to get the callback... */
  384. ret = utils->getcallback(utils->conn, id,
  385. (sasl_callback_ft *)&chalprompt_cb, &chalprompt_context);
  386. if (ret == SASL_OK && chalprompt_cb) {
  387. ret = chalprompt_cb(chalprompt_context, id,
  388. challenge, promptstr, NULL, result, NULL);
  389. if (ret != SASL_OK)
  390. return ret;
  391. if (!*result) {
  392. PARAMERROR(utils);
  393. return SASL_BADPARAM;
  394. }
  395. }
  396. return ret;
  397. }
  398. /*
  399. * Retrieve the client realm.
  400. */
  401. int _plug_get_realm(const sasl_utils_t *utils, const char **availrealms,
  402. const char **realm, sasl_interact_t **prompt_need)
  403. {
  404. int ret = SASL_FAIL;
  405. sasl_getrealm_t *realm_cb;
  406. void *realm_context;
  407. sasl_interact_t *prompt;
  408. *realm = NULL;
  409. /* see if we were given the result in the prompt */
  410. prompt = _plug_find_prompt(prompt_need, SASL_CB_GETREALM);
  411. if (prompt != NULL) {
  412. /* We prompted, and got.*/
  413. if (!prompt->result) {
  414. SETERROR(utils, "Unexpectedly missing a prompt result in _plug_get_realm");
  415. return SASL_BADPARAM;
  416. }
  417. *realm = prompt->result;
  418. return SASL_OK;
  419. }
  420. /* Try to get the callback... */
  421. ret = utils->getcallback(utils->conn, SASL_CB_GETREALM,
  422. (sasl_callback_ft *)&realm_cb, &realm_context);
  423. if (ret == SASL_OK && realm_cb) {
  424. ret = realm_cb(realm_context, SASL_CB_GETREALM, availrealms, realm);
  425. if (ret != SASL_OK)
  426. return ret;
  427. if (!*realm) {
  428. PARAMERROR(utils);
  429. return SASL_BADPARAM;
  430. }
  431. }
  432. return ret;
  433. }
  434. /*
  435. * Make the requested prompts. (prompt==NULL means we don't want it)
  436. */
  437. int _plug_make_prompts(const sasl_utils_t *utils,
  438. sasl_interact_t **prompts_res,
  439. const char *user_prompt, const char *user_def,
  440. const char *auth_prompt, const char *auth_def,
  441. const char *pass_prompt, const char *pass_def,
  442. const char *echo_chal,
  443. const char *echo_prompt, const char *echo_def,
  444. const char *realm_chal,
  445. const char *realm_prompt, const char *realm_def)
  446. {
  447. int num = 1;
  448. int alloc_size;
  449. sasl_interact_t *prompts;
  450. if (user_prompt) num++;
  451. if (auth_prompt) num++;
  452. if (pass_prompt) num++;
  453. if (echo_prompt) num++;
  454. if (realm_prompt) num++;
  455. if (num == 1) {
  456. SETERROR( utils, "make_prompts() called with no actual prompts" );
  457. return SASL_FAIL;
  458. }
  459. alloc_size = sizeof(sasl_interact_t)*num;
  460. prompts = utils->malloc(alloc_size);
  461. if (!prompts) {
  462. MEMERROR( utils );
  463. return SASL_NOMEM;
  464. }
  465. memset(prompts, 0, alloc_size);
  466. *prompts_res = prompts;
  467. if (user_prompt) {
  468. (prompts)->id = SASL_CB_USER;
  469. (prompts)->challenge = "Authorization Name";
  470. (prompts)->prompt = user_prompt;
  471. (prompts)->defresult = user_def;
  472. prompts++;
  473. }
  474. if (auth_prompt) {
  475. (prompts)->id = SASL_CB_AUTHNAME;
  476. (prompts)->challenge = "Authentication Name";
  477. (prompts)->prompt = auth_prompt;
  478. (prompts)->defresult = auth_def;
  479. prompts++;
  480. }
  481. if (pass_prompt) {
  482. (prompts)->id = SASL_CB_PASS;
  483. (prompts)->challenge = "Password";
  484. (prompts)->prompt = pass_prompt;
  485. (prompts)->defresult = pass_def;
  486. prompts++;
  487. }
  488. if (echo_prompt) {
  489. (prompts)->id = SASL_CB_ECHOPROMPT;
  490. (prompts)->challenge = echo_chal;
  491. (prompts)->prompt = echo_prompt;
  492. (prompts)->defresult = echo_def;
  493. prompts++;
  494. }
  495. if (realm_prompt) {
  496. (prompts)->id = SASL_CB_GETREALM;
  497. (prompts)->challenge = realm_chal;
  498. (prompts)->prompt = realm_prompt;
  499. (prompts)->defresult = realm_def;
  500. prompts++;
  501. }
  502. /* add the ending one */
  503. (prompts)->id = SASL_CB_LIST_END;
  504. (prompts)->challenge = NULL;
  505. (prompts)->prompt = NULL;
  506. (prompts)->defresult = NULL;
  507. return SASL_OK;
  508. }
  509. void _plug_decode_init(decode_context_t *text,
  510. const sasl_utils_t *utils, unsigned int in_maxbuf)
  511. {
  512. memset(text, 0, sizeof(decode_context_t));
  513. text->utils = utils;
  514. text->needsize = 4;
  515. text->in_maxbuf = in_maxbuf;
  516. }
  517. /*
  518. * Decode as much of the input as possible (possibly none),
  519. * using decode_pkt() to decode individual packets.
  520. */
  521. int _plug_decode(decode_context_t *text,
  522. const char *input, unsigned inputlen,
  523. char **output, /* output buffer */
  524. unsigned *outputsize, /* current size of output buffer */
  525. unsigned *outputlen, /* length of data in output buffer */
  526. int (*decode_pkt)(void *rock,
  527. const char *input, unsigned inputlen,
  528. char **output, unsigned *outputlen),
  529. void *rock)
  530. {
  531. unsigned int tocopy;
  532. unsigned diff;
  533. char *tmp;
  534. unsigned tmplen;
  535. int ret;
  536. *outputlen = 0;
  537. while (inputlen) { /* more input */
  538. if (text->needsize) { /* need to get the rest of the 4-byte size */
  539. /* copy as many bytes (up to 4) as we have into size buffer */
  540. tocopy = (inputlen > text->needsize) ? text->needsize : inputlen;
  541. memcpy(text->sizebuf + 4 - text->needsize, input, tocopy);
  542. text->needsize -= tocopy;
  543. input += tocopy;
  544. inputlen -= tocopy;
  545. if (!text->needsize) { /* we have the entire 4-byte size */
  546. memcpy(&(text->size), text->sizebuf, 4);
  547. text->size = ntohl(text->size);
  548. text->cursize = 0;
  549. } else {
  550. /* We do NOT have the entire 4-byte size...
  551. * wait for more data */
  552. return SASL_OK;
  553. }
  554. }
  555. if (!text->size) /* should never happen */
  556. return SASL_FAIL;
  557. if (text->size > text->in_maxbuf) {
  558. text->utils->log(NULL, SASL_LOG_ERR,
  559. "encoded packet size too big (%d > %d)",
  560. text->size, text->in_maxbuf);
  561. return SASL_FAIL;
  562. }
  563. if (!text->buffer) {
  564. text->buffer = text->utils->malloc(text->in_maxbuf);
  565. if (text->buffer == NULL) return SASL_NOMEM;
  566. }
  567. diff = text->size - text->cursize; /* bytes needed for full packet */
  568. if (inputlen < diff) { /* not a complete packet, need more input */
  569. memcpy(text->buffer + text->cursize, input, inputlen);
  570. text->cursize += inputlen;
  571. return SASL_OK;
  572. }
  573. /* copy the rest of the packet */
  574. memcpy(text->buffer + text->cursize, input, diff);
  575. input += diff;
  576. inputlen -= diff;
  577. /* decode the packet (no need to free tmp) */
  578. ret = decode_pkt(rock, text->buffer, text->size, &tmp, &tmplen);
  579. if (ret != SASL_OK) return ret;
  580. /* append the decoded packet to the output */
  581. ret = _plug_buf_alloc(text->utils, output, outputsize,
  582. *outputlen + tmplen + 1); /* +1 for NUL */
  583. if (ret != SASL_OK) return ret;
  584. memcpy(*output + *outputlen, tmp, tmplen);
  585. *outputlen += tmplen;
  586. /* protect stupid clients */
  587. *(*output + *outputlen) = '\0';
  588. /* reset for the next packet */
  589. text->needsize = 4;
  590. }
  591. return SASL_OK;
  592. }
  593. void _plug_decode_free(decode_context_t *text)
  594. {
  595. if (text->buffer) text->utils->free(text->buffer);
  596. }
  597. /* returns the realm we should pretend to be in */
  598. int _plug_parseuser(const sasl_utils_t *utils,
  599. char **user, char **realm, const char *user_realm,
  600. const char *serverFQDN, const char *input)
  601. {
  602. int ret;
  603. char *r;
  604. if(!user || !serverFQDN) {
  605. PARAMERROR( utils );
  606. return SASL_BADPARAM;
  607. }
  608. r = strchr(input, '@');
  609. if (!r) {
  610. /* hmmm, the user didn't specify a realm */
  611. if(user_realm && user_realm[0]) {
  612. ret = _plug_strdup(utils, user_realm, realm, NULL);
  613. } else {
  614. /* Default to serverFQDN */
  615. ret = _plug_strdup(utils, serverFQDN, realm, NULL);
  616. }
  617. if (ret == SASL_OK) {
  618. ret = _plug_strdup(utils, input, user, NULL);
  619. }
  620. } else {
  621. r++;
  622. ret = _plug_strdup(utils, r, realm, NULL);
  623. *--r = '\0';
  624. *user = utils->malloc(r - input + 1);
  625. if (*user) {
  626. strncpy(*user, input, r - input +1);
  627. } else {
  628. MEMERROR( utils );
  629. ret = SASL_NOMEM;
  630. }
  631. *r = '@';
  632. }
  633. return ret;
  634. }
  635. int _plug_make_fulluser(const sasl_utils_t *utils,
  636. char **fulluser,
  637. const char * useronly,
  638. const char *realm)
  639. {
  640. if(!fulluser || !useronly || !realm) {
  641. PARAMERROR( utils );
  642. return (SASL_BADPARAM);
  643. }
  644. *fulluser = utils->malloc (strlen(useronly) + strlen(realm) + 2);
  645. if (*fulluser == NULL) {
  646. MEMERROR( utils );
  647. return (SASL_NOMEM);
  648. }
  649. strcpy (*fulluser, useronly);
  650. strcat (*fulluser, "@");
  651. strcat (*fulluser, realm);
  652. return (SASL_OK);
  653. }
  654. char * _plug_get_error_message (const sasl_utils_t *utils,
  655. #ifdef WIN32
  656. DWORD error
  657. #else
  658. int error
  659. #endif
  660. )
  661. {
  662. char * return_value;
  663. #ifdef WIN32
  664. LPVOID lpMsgBuf;
  665. FormatMessage(
  666. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  667. FORMAT_MESSAGE_FROM_SYSTEM |
  668. FORMAT_MESSAGE_IGNORE_INSERTS,
  669. NULL,
  670. error,
  671. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
  672. (LPTSTR) &lpMsgBuf,
  673. 0,
  674. NULL
  675. );
  676. if (_plug_strdup (utils, lpMsgBuf, &return_value, NULL) != SASL_OK) {
  677. return_value = NULL;
  678. }
  679. LocalFree( lpMsgBuf );
  680. #else /* !WIN32 */
  681. if (_plug_strdup (utils, strerror(error), &return_value, NULL) != SASL_OK) {
  682. return_value = NULL;
  683. }
  684. #endif /* WIN32 */
  685. return (return_value);
  686. }
  687. void _plug_snprintf_os_info (char * osbuf, int osbuf_len)
  688. {
  689. #ifdef WIN32
  690. char *sysname;
  691. sysname = "Unknown Windows";
  692. /* Let's suppose it's still compilable with win2k sdk. So define everythig missing */
  693. #ifndef _WIN32_WINNT_WINXP
  694. # define _WIN32_WINNT_WINXP 0x0501
  695. #endif
  696. #ifndef _WIN32_WINNT_WS03
  697. # define _WIN32_WINNT_WS03 0x0502
  698. #endif
  699. #ifndef _WIN32_WINNT_WIN6
  700. # define _WIN32_WINNT_WIN6 0x0600
  701. #endif
  702. #ifndef _WIN32_WINNT_VISTA
  703. # define _WIN32_WINNT_VISTA 0x0600
  704. #endif
  705. #ifndef _WIN32_WINNT_WS08
  706. # define _WIN32_WINNT_WS08 0x0600
  707. #endif
  708. #ifndef _WIN32_WINNT_LONGHORN
  709. # define _WIN32_WINNT_LONGHORN 0x0600
  710. #endif
  711. #ifndef _WIN32_WINNT_WIN7
  712. # define _WIN32_WINNT_WIN7 0x0601
  713. #endif
  714. #ifndef _WIN32_WINNT_WIN8
  715. # define _WIN32_WINNT_WIN8 0x0602
  716. #endif
  717. #ifndef _WIN32_WINNT_WINBLUE
  718. # define _WIN32_WINNT_WINBLUE 0x0603
  719. #endif
  720. #ifndef _WIN32_WINNT_WIN10
  721. # define _WIN32_WINNT_WIN10 0x0A00
  722. #endif
  723. /* and use IsWindowsVersionOrGreater instead of convenient wrappers by the same reason */
  724. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0)) {
  725. sysname = "Windows 10 or greater";
  726. } else
  727. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0)) {
  728. sysname = "Windows 8.1";
  729. } else
  730. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0)) {
  731. sysname = "Windows 8";
  732. } else
  733. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1)) {
  734. sysname = "Windows 7 SP1";
  735. } else
  736. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0)) {
  737. sysname = "Windows 7";
  738. } else
  739. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2)) {
  740. sysname = "Windows Vista SP2";
  741. } else
  742. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1)) {
  743. sysname = "Windows Vista SP1";
  744. } else
  745. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0)) {
  746. sysname = "Windows Vista";
  747. } else
  748. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3)) {
  749. sysname = "Windows XP SP3";
  750. } else
  751. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2)) {
  752. sysname = "Windows XP SP2";
  753. } else
  754. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1)) {
  755. sysname = "Windows XP SP1";
  756. } else
  757. if (IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0)) {
  758. sysname = "Windows XP";
  759. }
  760. snprintf(osbuf, osbuf_len, "%s", sysname);
  761. #else /* !WIN32 */
  762. struct utsname os;
  763. uname(&os);
  764. snprintf(osbuf, osbuf_len, "%s %s", os.sysname, os.release);
  765. #endif /* WIN32 */
  766. }
  767. #if defined(WIN32)
  768. unsigned int plug_sleep (unsigned int seconds)
  769. {
  770. long dwSec = seconds*1000;
  771. Sleep (dwSec);
  772. return 0;
  773. }
  774. #endif