61 #include <netinet/in.h>
62 #include <sys/types.h>
64 #include <sys/socket.h>
66 #include <sasl/sasl.h>
70 static struct mbdyn_sasl_t global_mbdyn_sasl = MBDYN_SASL_INIT;
73 get_secret_default_f(sasl_conn_t *conn,
76 sasl_secret_t **psecret)
79 const char *cred = global_mbdyn_sasl.sasl_cred;
81 if (
id != SASL_CB_PASS)
return SASL_FAIL;
84 cred = getpass(
"password: ");
87 credlen = strlen(cred);
88 *psecret = malloc(
sizeof(sasl_secret_t) + credlen);
89 (*psecret)->len = credlen;
90 memcpy(&(*psecret)->data[0], cred, credlen);
96 get_authname_default_f(
void *context,
101 const char *authz = global_mbdyn_sasl.sasl_authz;
102 char buf[MBDYN_SASL_BUFSIZE];
104 if (
id != SASL_CB_AUTHNAME)
return SASL_FAIL;
106 if (!authz && (global_mbdyn_sasl.sasl_flags & MBDYN_SASL_FLAG_USERAUTHZ)) {
107 authz = global_mbdyn_sasl.sasl_user;
113 printf(
"authzname: ");
114 if (fgets(buf,
sizeof(buf), stdin) == NULL) {
118 buflen = strlen(buf);
119 if (buf[buflen - 1] ==
'\n') {
130 *result = strdup(authz);
132 *len = strlen(*result);
145 get_user_default_f(
void *context,
150 const char *user = global_mbdyn_sasl.sasl_user;
151 char buf[MBDYN_SASL_BUFSIZE];
153 if (
id != SASL_CB_USER)
return SASL_FAIL;
158 printf(
"username: ");
159 if (fgets(buf,
sizeof(buf), stdin) == NULL) {
163 buflen = strlen(buf);
164 if (buf[buflen - 1] ==
'\n') {
171 *result = strdup(user);
173 *len = strlen(*result);
180 get_realm_default_f(
void *context,
182 const char **availrealms,
185 const char *realm = global_mbdyn_sasl.sasl_realm;
186 char buf[MBDYN_SASL_BUFSIZE];
188 if (
id != SASL_CB_GETREALM)
return SASL_FAIL;
194 if (fgets(buf,
sizeof(buf), stdin) == NULL) {
198 buflen = strlen(buf);
199 if (buf[buflen - 1] ==
'\n') {
210 *result = strdup(realm);
219 log_server_default_f(
void *context,
223 fprintf(stderr,
"[server %d] %s\n", level, message);
228 log_client_default_f(
void *context,
232 fprintf(stderr,
"[client %d] %s\n", level, message);
236 sasl_log_t *log_server_f = &log_server_default_f;
237 sasl_log_t *log_client_f = &log_client_default_f;
238 sasl_getsimple_t *get_user_f = &get_user_default_f;
239 sasl_getsimple_t *get_authname_f = &get_authname_default_f;
240 sasl_getsecret_t *get_secret_f = &get_secret_default_f;
241 sasl_getrealm_t *get_realm_f = &get_realm_default_f;
243 static sasl_callback_t server_callbacks[] = {
244 { SASL_CB_LOG, NULL , NULL },
245 { SASL_CB_LIST_END, NULL, NULL }
248 static sasl_callback_t client_callbacks[] = {
249 { SASL_CB_GETREALM, NULL , NULL },
250 { SASL_CB_USER, NULL , NULL },
251 { SASL_CB_AUTHNAME, NULL , NULL },
252 { SASL_CB_PASS, NULL , NULL },
253 { SASL_CB_LOG, NULL , NULL },
254 { SASL_CB_LIST_END, NULL, NULL }
258 mbdyn_sasl_client_init(
struct mbdyn_sasl_t *mbdyn_sasl)
262 client_callbacks[0].proc = get_realm_f;
263 client_callbacks[1].proc = get_user_f;
264 client_callbacks[2].proc = get_authname_f;
265 client_callbacks[3].proc = get_secret_f;
266 client_callbacks[4].proc = log_client_f;
269 global_mbdyn_sasl = *mbdyn_sasl;
272 rc = sasl_client_init(client_callbacks);
274 printf(
"[client] sasl_client_init() failed: %d (%s)\n",
275 rc, sasl_errstring(rc, NULL, NULL));
282 mbdyn_sasl_server_init(
struct mbdyn_sasl_t *mbdyn_sasl)
286 server_callbacks[0].proc = log_server_f;
288 rc = sasl_server_init(server_callbacks,
289 MBDYN_SASL_CONFFILE);
293 printf(
"[server] sasl_server_init() failed: %d (%s)\n",
294 rc, sasl_errstring(rc, NULL, NULL));
301 mbdyn_sasl_init(
struct mbdyn_sasl_t *mbdyn_sasl)
303 switch (mbdyn_sasl->use_sasl) {
304 case MBDYN_SASL_SERVER:
305 return mbdyn_sasl_server_init(mbdyn_sasl);
308 case MBDYN_SASL_CLIENT:
309 return mbdyn_sasl_client_init(mbdyn_sasl);
314 if (mbdyn_sasl->sasl_flags & MBDYN_SASL_FLAG_CRITICAL) {
322 mbdyn_sasl_fini(
void)
330 mbdyn_sasl_client_auth(
int sock,
struct sockaddr *bindaddr,
331 struct mbdyn_sasl_t *mbdyn_sasl)
334 sasl_conn_t *conn = NULL;
335 sasl_interact_t *client_interact = NULL;
336 const char *out = NULL, *mechusing = NULL;
339 sasl_security_properties_t secprops;
344 char serverin[MBDYN_SASL_BUFSIZE] = {
'\0' };
345 const char *mech = NULL;
346 unsigned serverinlen = 0;
348 int oldflags, currflags;
350 oldflags = fcntl (sock, F_GETFL, 0);
351 if (oldflags == -1) {
354 currflags = oldflags & ~O_NONBLOCK;
355 if (fcntl(sock, F_SETFL, currflags) == -1) {
359 rc = sasl_client_new(MBDYN_SASL_SERVICE,
360 mbdyn_sasl->sasl_hostname,
363 mbdyn_sasl->sasl_local_ip,
364 mbdyn_sasl->sasl_remote_ip,
372 printf(
"[client] sasl_client_new() failed: %d (%s)\n",
373 rc, sasl_errstring(rc, NULL, NULL));
378 count = write(sock,
"M", 1);
381 if (errno == EINVAL && mbdyn_sasl->sasl_usleep) {
382 usleep(mbdyn_sasl->sasl_usleep);
385 printf(
"[client] write() failed errno=%d\n", errno);
387 printf(
"[client] write() failed (%d instead of %d)\n", count , 1);
393 count =
read(sock, &op, 1);
396 printf(
"[client] read(M) failed errno=%d\n", errno);
398 printf(
"[client] read(M) failed (%d instead of %d)\n", count, 1);
405 printf(
"[client] expecting \"M\" with methods\n");
411 count =
read(sock, &serverinlen,
sizeof(
unsigned));
412 if (count !=
sizeof(
unsigned)) {
414 printf(
"[client] read(Ml) failed errno=%d\n", errno);
416 printf(
"[client] read(Ml) failed (%d instead of %u)\n",
417 count, (
unsigned)
sizeof(
unsigned));
422 if (serverinlen >=
sizeof(serverin)) {
423 printf(
"[client] buffer for mechanism list is too small\n");
427 count =
read(sock, serverin, serverinlen);
428 if (count < 0 || (
unsigned)count != serverinlen) {
430 printf(
"[client] read(Md) failed errno=%d\n", errno);
432 printf(
"[client] read(Md) failed (%d instead of %d)\n",
438 serverin[
count] =
'\0';
440 mech = mbdyn_sasl->sasl_mech;
446 memset(&secprops, 0,
sizeof(secprops));
447 secprops.min_ssf = 1;
448 secprops.max_ssf = 256;
449 secprops.maxbufsize = MBDYN_SASL_BUFSIZE;
451 secprops.property_names = NULL;
452 secprops.property_values = NULL;
453 secprops.security_flags = SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT | SASL_SEC_MUTUAL_AUTH;
455 sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
459 char buf[MBDYN_SASL_BUFSIZE];
461 rc = sasl_client_start(conn,
471 if (rc == SASL_INTERACT) {
472 if (!(mbdyn_sasl->sasl_flags & MBDYN_SASL_FLAG_INTERACT)) {
473 printf(
"[client] interaction disabled\n");
479 printf(
"[client] sasl_client_start() requested "
480 "interaction \"%s\"; mech=%s\n",
481 client_interact->prompt, mechusing);
484 if (outlen >=
sizeof(buf)) {
485 printf(
"[client] buf is too small\n");
489 memcpy(buf, out, outlen);
491 }
while (rc == SASL_INTERACT);
502 printf(
"[client] sasl start failure\n");
507 count = write(sock,
"S", 1);
510 printf(
"[client] write() failed errno=%d\n", errno);
512 printf(
"[client] write() failed (%d instead of %d)\n", count, 1);
517 serverinlen = strlen(mechusing);
518 count = write(sock, &serverinlen,
sizeof(
unsigned));
519 if (count !=
sizeof(
unsigned)) {
521 printf(
"[client] write() failed errno=%d\n", errno);
523 printf(
"[client] write() failed (%d instead of %u)\n",
524 count, (
unsigned)
sizeof(
unsigned));
529 count = write(sock, mechusing, serverinlen);
530 if (count < 0 || (
unsigned)count != serverinlen) {
532 printf(
"[client] mech=\"%s\" write failed errno=%d\n",
535 printf(
"[client] mech=\"%s\" write failed "
536 "(%d instead of %d)\n",
537 mechusing, count, serverinlen);
543 count = write(sock, &outlen,
sizeof(
unsigned));
544 if (count < 0 || (
unsigned)count !=
sizeof(
unsigned)) {
546 printf(
"[client] write() failed errno=%d\n", errno);
548 printf(
"[client] write() failed (%d instead of %u)\n",
549 count, (
unsigned)
sizeof(
unsigned));
554 count = write(sock, out ? out :
"", outlen);
555 if (count < 0 || (
unsigned)count != outlen) {
557 printf(
"[client] mech=\"%s\" write failed errno=%d\n",
560 printf(
"[client] mech=\"%s\" write failed "
561 "(%d instead of %d)\n",
562 mechusing, count, outlen);
572 count =
read(sock, &op, 1);
575 printf(
"[client] read(c) failed errno=%d\n", errno);
577 printf(
"[client] read(c) failed (%d instead of %d)\n", count, 1);
596 count =
read(sock, serverin,
sizeof(
unsigned));
597 if (count !=
sizeof(
unsigned)) {
599 printf(
"[client] read(Cd) failed errno=%d\n", errno);
601 printf(
"[client] read(Cd) failed "
602 "(%d instead of %u)\n",
603 count, (
unsigned)
sizeof(
unsigned));
608 serverinlen = ((
unsigned *)(serverin))[0];
609 if (serverinlen >=
sizeof(serverin)) {
610 printf(
"[client] buffer for "
611 "sasl_client_step() "
617 count =
read(sock, serverin, serverinlen);
618 if (count < 0 || (
unsigned)count != serverinlen) {
620 printf(
"[client] read() failed errno=%d\n", errno);
622 printf(
"[client] read() failed (%d instead of %d)\n",
628 serverin[serverinlen] =
'\0';
635 rc = sasl_client_step(conn,
644 count = write(sock,
"C", 1);
647 printf(
"[client] write failed errno=%d\n", errno);
649 printf(
"[client] write failed (%d instead of %d)\n", count, 1);
655 count = write(sock, &outlen,
sizeof(
unsigned));
656 if (count !=
sizeof(
unsigned)) {
658 printf(
"[client] write failed errno=%d\n", errno);
660 printf(
"[client] write failed "
661 "(%d instead of %u)\n",
662 count, (
unsigned)
sizeof(
unsigned));
667 count = write(sock, out ? out :
"", outlen);
668 if (count < 0 || (
unsigned)count != outlen) {
670 printf(
"[client] write failed errno=%d\n", errno);
672 printf(
"[client] write failed (%d instead of %d)\n", count, outlen);
693 }
while (rc == SASL_INTERACT || rc == SASL_CONTINUE || rc == SASL_OK);
696 printf(
"[client] sasl step failure\n");
705 char buf[MBDYN_SASL_BUFSIZE];
706 int ssf = 0, outbufsize = MBDYN_SASL_BUFSIZE;
707 const int *ssfp = &ssf, *outbufsizep = &outbufsize;
709 rc = sasl_getprop(conn, SASL_SSF, (
const void **)&ssfp);
711 fprintf(stderr,
"[client] unable to retrieve ssf\n");
716 rc = sasl_getprop(conn, SASL_MAXOUTBUF, (
const void **)&outbufsizep);
718 fprintf(stderr,
"[client] unable to retrieve out buf size\n");
721 outbufsize = *outbufsizep;
724 fprintf(stderr,
"[client] SASL_OK (ssf=%d, outbufsize=%d)\n", ssf, outbufsize);
733 if (fcntl (sock, F_SETFL, oldflags) == -1) {
741 mbdyn_sasl_server_auth(
int sock,
struct sockaddr *bindaddr,
742 struct mbdyn_sasl_t *mbdyn_sasl)
745 sasl_conn_t *conn = NULL;
746 const char *result_string = NULL;
747 unsigned string_length = 0;
748 int number_of_mechanisms = 0;
749 const char *out = NULL;
752 sasl_security_properties_t secprops;
757 char mechanism_client_chose[MBDYN_SASL_BUFSIZE] = {
'\0' };
758 char clientin[MBDYN_SASL_BUFSIZE] = {
'\0' };
759 unsigned clientinlen = 0;
761 int oldflags, currflags;
763 oldflags = fcntl (sock, F_GETFL, 0);
764 if (oldflags == -1) {
767 currflags = oldflags & ~O_NONBLOCK;
768 if (fcntl(sock, F_SETFL, currflags) == -1) {
772 rc = sasl_server_new(MBDYN_SASL_SERVICE,
775 mbdyn_sasl->sasl_realm,
779 mbdyn_sasl->sasl_local_ip,
780 mbdyn_sasl->sasl_remote_ip,
789 printf(
"[server] sasl_server_new() failed: %d (%s)\n",
790 rc, sasl_errstring(rc, NULL, NULL));
795 memset(&secprops, 0,
sizeof(secprops));
796 secprops.min_ssf = 1;
797 secprops.max_ssf = 256;
798 secprops.maxbufsize = MBDYN_SASL_BUFSIZE;
800 secprops.property_names = NULL;
801 secprops.property_values = NULL;
802 secprops.security_flags = SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT | SASL_SEC_MUTUAL_AUTH;
804 sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
808 count =
read(sock, &op, 1);
811 if (errno == EINVAL && mbdyn_sasl->sasl_usleep) {
812 usleep(mbdyn_sasl->sasl_usleep);
815 printf(
"[server] read failed errno=%d\n", errno);
817 printf(
"[server] read failed (%d instead of %d)\n", count, 2);
824 printf(
"[server] \"M\" expected\n");
829 rc = sasl_listmech(conn,
836 &number_of_mechanisms);
839 printf(
"[server] sasl_listmech() failed: %s\n",
840 sasl_errdetail(conn));
845 count = write(sock,
"M", 1);
848 printf(
"[server] write() failed errno=%d\n", errno);
850 printf(
"[server] write() failed (%d instead of %d)\n", count, 1);
855 count = write(sock, &string_length,
sizeof(
unsigned));
856 if (count !=
sizeof(
unsigned)) {
858 printf(
"[server] write() failed errno=%d\n", errno);
860 printf(
"[server] write() failed (%d instead of %u)\n",
861 count, (
unsigned)
sizeof(
unsigned));
866 count = write(sock, result_string, string_length);
867 if (count < 0 || (
unsigned)count != string_length) {
869 printf(
"[server] write() failed errno=%d\n", errno);
871 printf(
"[server] write() failed (%d instead of %d)\n",
872 count, string_length);
879 count =
read(sock, &op, 1);
882 printf(
"[server] read() failed errno=%d\n", errno);
884 printf(
"[server] read() failed (%d instead of %d)\n",
893 printf(
"[server] expecting \"S\" to start auth\n");
898 count =
read(sock, &clientinlen,
sizeof(
unsigned));
899 if (count !=
sizeof(
unsigned)) {
901 printf(
"[server] read() failed errno=%d\n", errno);
903 printf(
"[server] read() failed (%d instead of %u)\n",
904 count, (
unsigned)
sizeof(
unsigned));
909 if (clientinlen >=
sizeof(mechanism_client_chose)) {
910 printf(
"[server] buffer for mechanism too small\n");
914 count =
read(sock, mechanism_client_chose, clientinlen);
915 if (count < 0 || (
unsigned)count != clientinlen) {
917 printf(
"[server] read() failed errno=%d\n", errno);
919 printf(
"[server] read() failed (%d instead of %u)\n",
925 mechanism_client_chose[clientinlen] =
'\0';
928 count =
read(sock, &clientinlen,
sizeof(
unsigned));
929 if (count !=
sizeof(
unsigned)) {
931 printf(
"[server] read() failed errno=%d\n", errno);
933 printf(
"[server] read() failed (%d instead of %u)\n",
934 count, (
unsigned)
sizeof(
unsigned));
939 if (clientinlen >=
sizeof(clientin)) {
940 printf(
"[server] buffer for client optional string "
945 count =
read(sock, clientin, clientinlen);
946 if (count < 0 || (
unsigned)count != clientinlen) {
948 printf(
"[server] read() failed errno=%d\n", errno);
950 printf(
"[server] read() failed (%d instead of %u)\n",
956 clientin[clientinlen] =
'\0';
958 rc = sasl_server_start(conn,
959 mechanism_client_chose,
960 clientinlen ? clientin : NULL,
970 count = write(sock,
"O", 1);
973 printf(
"[server] write() failed errno=%d\n", errno);
975 printf(
"[server] write() failed (%d instead of %d)\n", count, 1);
981 case SASL_CONTINUE: {
982 char buf[MBDYN_SASL_BUFSIZE];
984 if (1 + outlen +
sizeof(
unsigned) >=
sizeof(buf)) {
985 printf(
"[server] buffer for "
986 "sasl_server_step() "
994 memcpy(buf + 1, &outlen,
sizeof(
unsigned));
995 memcpy(buf + 1 +
sizeof(
unsigned), out, outlen);
997 count = write(sock, buf, 1 + outlen +
sizeof(
unsigned));
998 if (count < 0 || (
unsigned)count != 1 + outlen +
sizeof(
unsigned)) {
1000 printf(
"[server] write() failed errno=%d\n", count);
1002 printf(
"[server] write() failed "
1003 "(%d instead of %u)\n",
1005 (
unsigned)(1 + outlen +
sizeof(
unsigned)));
1014 count = write(sock,
"F", 1);
1017 printf(
"[server] write() failed errno=%d\n", errno);
1019 printf(
"[server] write() failed (%d instead of %d)\n", count, 1);
1026 count =
read(sock, &op, 1);
1029 printf(
"[server] read() failed errno=%d\n", errno);
1031 printf(
"[server] read() failed (%d instead of %d)\n", count, 1);
1038 printf(
"[server] expecting \"C\" to continue\n");
1047 count =
read(sock, &clientinlen,
sizeof(
unsigned));
1048 if (count !=
sizeof(
unsigned)) {
1050 printf(
"[server] read() failed errno=%d\n", errno);
1052 printf(
"[server] read() failed "
1053 "(%d instead of %u)\n",
1054 count, (
unsigned)
sizeof(
unsigned));
1059 if (clientinlen >=
sizeof(clientin)) {
1060 printf(
"[server] buffer for sasl_server_step() "
1061 "client data is too small\n");
1065 count =
read(sock, clientin, clientinlen);
1066 if (count < 0 || (
unsigned)count != clientinlen) {
1068 printf(
"[server] read() failed errno=%d\n", errno);
1070 printf(
"[server] read() failed "
1071 "(%d instead of %u)\n",
1072 count, clientinlen);
1078 rc = sasl_server_step(conn,
1090 sasl_dispose(&conn);
1093 if (fcntl (sock, F_SETFL, oldflags) == -1) {
1101 mbdyn_sasl_auth(
int sock,
struct sockaddr *bindaddr,
1102 struct mbdyn_sasl_t *mbdyn_sasl)
1104 switch (mbdyn_sasl->use_sasl) {
1105 case MBDYN_SASL_SERVER:
1106 return mbdyn_sasl_server_auth(sock, bindaddr, mbdyn_sasl);
1109 case MBDYN_SASL_CLIENT:
1110 return mbdyn_sasl_client_auth(sock, bindaddr, mbdyn_sasl);
1115 if (mbdyn_sasl->sasl_flags & MBDYN_SASL_FLAG_CRITICAL) {
1123 mbdyn_sasl_validate(
struct mbdyn_sasl_t *mbdyn_sasl)
1125 switch (mbdyn_sasl->use_sasl) {
1126 case MBDYN_SASL_NONE:
1129 case MBDYN_SASL_SERVER:
1130 if (mbdyn_sasl->sasl_user != NULL) {
1134 if (mbdyn_sasl->sasl_cred != NULL) {
1138 if (mbdyn_sasl->sasl_authz != NULL) {
1144 case MBDYN_SASL_CLIENT:
1145 if (mbdyn_sasl->sasl_hostname == NULL) {
1146 mbdyn_sasl->sasl_hostname =
"localhost";
1170 mbdyn_sasl_parse_args(
int opt,
const char *
optarg,
1171 struct mbdyn_sasl_t *mbdyn_sasl)
1175 mbdyn_sasl->sasl_authz = optarg[0] ? optarg : NULL;
1179 if (strcasecmp(optarg,
"userauthz") == 0) {
1180 mbdyn_sasl->sasl_flags |= MBDYN_SASL_FLAG_USERAUTHZ;
1182 }
else if (strcasecmp(optarg,
"interact") == 0) {
1183 mbdyn_sasl->sasl_flags |= MBDYN_SASL_FLAG_INTERACT;
1186 printf(
"UNKNOWN FLAG '%s'\n", optarg);
1191 mbdyn_sasl->sasl_hostname = optarg[0] ? optarg : NULL;
1195 mbdyn_sasl->sasl_remote_ip = optarg[0] ? optarg : NULL;
1199 mbdyn_sasl->sasl_local_ip = optarg[0] ? optarg : NULL;
1203 mbdyn_sasl->sasl_mech = optarg[0] ? optarg : NULL;
1207 mbdyn_sasl->sasl_realm = optarg[0] ? optarg : NULL;
1211 if (strcasecmp(optarg,
"server") == 0) {
1212 mbdyn_sasl->use_sasl = MBDYN_SASL_SERVER;
1213 }
else if (strcasecmp(optarg,
"client") == 0) {
1214 mbdyn_sasl->use_sasl = MBDYN_SASL_CLIENT;
1215 }
else if (strcasecmp(optarg,
"none") == 0) {
1216 mbdyn_sasl->use_sasl = MBDYN_SASL_NONE;
1218 printf(
"UNKNOWN SASL MODE; SASL DISABLED\n");
1219 mbdyn_sasl->use_sasl = MBDYN_SASL_NONE;
1228 l = strtoul(optarg, &next, 10);
1229 int save_errno = errno;
1230 if (next == NULL || next[0] !=
'\0') {
1231 printf(
"ILLEGAL SLEEP TIME '%s'\n", optarg);
1233 }
else if (save_errno == ERANGE) {
1234 printf(
"SLEEP TIME '%s' OVERFLOWS\n", optarg);
1237 mbdyn_sasl->sasl_usleep = l;
1243 mbdyn_sasl->sasl_user = optarg[0] ? optarg : NULL;
1247 mbdyn_sasl->sasl_cred = optarg[0] ? optarg : NULL;
static doublereal buf[BUFSIZE]
static void * read(LoadableElem *pEl, DataManager *pDM, MBDynParser &HP)