SASLSession::SASLSession(const string& serviceName, ref <SASLContext> ctx, ref <authenticator> auth, ref <SASLMechanism> mech) : m_serviceName(serviceName), m_context(ctx), m_auth(auth), m_mech(mech), m_gsaslContext(0), m_gsaslSession(0) { if (gsasl_init(&m_gsaslContext) != GSASL_OK) throw std::bad_alloc(); gsasl_client_start(m_gsaslContext, mech->getName().c_str(), &m_gsaslSession); gsasl_callback_set(m_gsaslContext, gsaslCallback); gsasl_callback_hook_set(m_gsaslContext, this); }
int main (int argc, char *argv[]) { const char *service = argc > 1 ? argv[1] : "2000"; volatile int run = 1; struct addrinfo hints, *addrs; int sockfd; int rc; int yes = 1; Gsasl *ctx; struct cfg cfg; setvbuf (stdout, NULL, _IONBF, 0); if (argc != 7) { printf ("Usage: %s PORT CFG-PATH STATE-PATH SP-METADATA " "SP-KEY SP-CERT\n", argv[0]); exit (EXIT_FAILURE); } cfg.cfg_path = argv[2]; cfg.state_path = argv[3]; cfg.sp_metadata = argv[4]; cfg.sp_key = argv[5]; cfg.sp_cert = argv[6]; rc = gsasl_init (&ctx); if (rc < 0) { printf ("gsasl_init (%d): %s\n", rc, gsasl_strerror (rc)); exit (EXIT_FAILURE); } printf ("%s [gsasl header %s library %s]\n", argv[0], GSASL_VERSION, gsasl_check_version (NULL)); gsasl_callback_set (ctx, callback); gsasl_callback_hook_set (ctx, &cfg); memset (&hints, 0, sizeof (hints)); hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; hints.ai_socktype = SOCK_STREAM; rc = getaddrinfo (NULL, service, &hints, &addrs); if (rc < 0) { printf ("getaddrinfo: %s\n", gai_strerror (rc)); exit (EXIT_FAILURE); } sockfd = socket (addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol); if (sockfd < 0) { perror ("socket"); exit (EXIT_FAILURE); } if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (yes)) < 0) { perror ("setsockopt"); exit (EXIT_FAILURE); } rc = bind (sockfd, addrs->ai_addr, addrs->ai_addrlen); if (rc < 0) { perror ("bind"); exit (EXIT_FAILURE); } freeaddrinfo (addrs); rc = listen (sockfd, SOMAXCONN); if (rc < 0) { perror ("listen"); exit (EXIT_FAILURE); } signal (SIGPIPE, SIG_IGN); while (run) { struct sockaddr from; socklen_t fromlen = sizeof (from); char host[NI_MAXHOST]; int fd; FILE *fh; fd = accept (sockfd, &from, &fromlen); if (fd < 0) { perror ("accept"); continue; } rc = getnameinfo (&from, fromlen, host, sizeof (host), NULL, 0, NI_NUMERICHOST); if (rc == 0) printf ("connection from %s\n", host); else printf ("getnameinfo: %s\n", gai_strerror (rc)); fh = fdopen (fd, "w+"); if (!fh) { perror ("fdopen"); close (fd); continue; } smtp (fh, ctx); fclose (fh); } close (sockfd); gsasl_done (ctx); return 0; }
static int sasl_auth(dico_stream_t str, char *mechanism, char *initresp, Gsasl_session **psess) { int rc; Gsasl_session *sess_ctx; char *input; char *output; char *inbuf; size_t insize; struct sasl_data sdata = { NULL, 0 }; if (disabled_mechanism_p(mechanism)) return RC_NOMECH; rc = gsasl_server_start (ctx, mechanism, &sess_ctx); if (rc != GSASL_OK) { dico_log(L_ERR, 0, _("SASL gsasl_server_start: %s"), gsasl_strerror(rc)); return rc == GSASL_UNKNOWN_MECHANISM ? RC_NOMECH : RC_FAIL; } gsasl_callback_hook_set(ctx, &sdata); output = NULL; if (initresp) { inbuf = xstrdup(initresp); insize = strlen(initresp) + 1; } else { inbuf = NULL; insize = 0; } input = inbuf; while ((rc = gsasl_step64(sess_ctx, input, &output)) == GSASL_NEEDS_MORE) { send_challenge(str, output); free(output); output = NULL; if (get_sasl_response(str, &input, &inbuf, &insize)) return RC_FAIL; } if (rc != GSASL_OK) { dico_log(L_ERR, 0, _("GSASL error: %s"), gsasl_strerror(rc)); free(output); free(inbuf); gsasl_finish(sess_ctx); return RC_FAIL; } /* Some SASL mechanisms output data when GSASL_OK is returned */ if (output[0]) send_challenge(str, output); free(output); free(inbuf); if (sdata.username == NULL) { dico_log(L_ERR, 0, _("GSASL %s: cannot get username"), mechanism); gsasl_finish(sess_ctx); return RC_FAIL; } user_name = xstrdup(sdata.username); if (sdata.anon) { if (sasl_anon_groups) { user_groups = xdico_list_create(); dico_list_iterate (sasl_anon_groups, _append_item, user_groups); } } else dico_udb_get_groups(user_db, sdata.username, &user_groups); check_db_visibility(); *psess = sess_ctx; return RC_SUCCESS; }
void doit (void) { Gsasl *ctx = NULL; Gsasl_session *sctx = NULL; char *out = NULL; int i, j; int res; if (!gsasl_check_version (GSASL_VERSION)) fail ("gsasl_check_version failure"); success ("Header version %s library version %s\n", GSASL_VERSION, gsasl_check_version (NULL)); res = gsasl_init (&ctx); if (res != GSASL_OK) { fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res)); return; } gsasl_callback_set (ctx, cb); res = gsasl_client_mechlist (ctx, &out); if (res != GSASL_OK) fail ("gsasl_client_mechlist() failed (%d):\n%s\n", res, gsasl_strerror (res)); success ("client_mechlist: %s\n", out); gsasl_free (out); out = NULL; res = gsasl_server_mechlist (ctx, &out); if (res != GSASL_OK) fail ("gsasl_server_mechlist() failed (%d):\n%s\n", res, gsasl_strerror (res)); success ("server_mechlist: %s\n", out); gsasl_free (out); out = NULL; for (i = 0; i < sizeof (sasltv) / sizeof (sasltv[0]); i++) { gsasl_callback_hook_set (ctx, &i); if (debug) printf ("Entry %d %s mechanism %s:\n", i, sasltv[i].clientp ? "client" : "server", sasltv[i].mech); if (sasltv[i].clientp) res = gsasl_client_support_p (ctx, sasltv[i].mech); else res = gsasl_server_support_p (ctx, sasltv[i].mech); if (!res) continue; if (sasltv[i].clientp) res = gsasl_client_start (ctx, sasltv[i].mech, &sctx); else res = gsasl_server_start (ctx, sasltv[i].mech, &sctx); if (res != GSASL_OK) { fail ("SASL %s start for mechanism %s failed (%d):\n%s\n", sasltv[i].clientp ? "client" : "server", sasltv[i].mech, res, gsasl_strerror (res)); continue; } for (j = 0; sasltv[i].step[j]; j += 2) { gsasl_session_hook_set (sctx, &j); if (debug) printf ("Input : %s\n", sasltv[i].step[j] ? sasltv[i].step[j] : ""); res = gsasl_step64 (sctx, sasltv[i].step[j], &out); if (debug) printf ("Output: %s\n", out ? out : "(null)"); if (res != GSASL_OK && res != GSASL_NEEDS_MORE) { fail ("gsasl_step64 failed (%d): %s", res, gsasl_strerror (res)); break; } if (strlen (out) != strlen (sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : "")) { printf ("Expected: %s\n", sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : ""); fail ("SASL entry %d mechanism %s client step %d length error\n", i, sasltv[i].mech, j); j = -1; break; } if (strcmp (out, sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : "") != 0) { printf ("Expected: %s\n", sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : ""); fail ("SASL entry %d mechanism %s client step %d data error\n", i, sasltv[i].mech, j); j = -1; break; } gsasl_free (out); out = NULL; if (strcmp (sasltv[i].mech, "SECURID") != 0 && res == GSASL_OK) break; } if (j != (size_t) - 1 && res == GSASL_OK && sasltv[i].step[j + 2]) fail ("SASL entry %d mechanism %s step %d code ended prematurely\n", i, sasltv[i].mech, j); else if (j != (size_t) - 1 && res == GSASL_NEEDS_MORE) fail ("SASL entry %d mechanism %s step %d table ended prematurely\n", i, sasltv[i].mech, j); else if (j != (size_t) - 1 && res != GSASL_OK) fail ("SASL entry %d mechanism %s step %d failed (%d):\n%s\n", i, sasltv[i].mech, j, res, gsasl_strerror (res)); else printf ("PASS: simple %s %s %d\n", sasltv[i].mech, sasltv[i].clientp ? "client" : "server", i); { size_t outlen; res = gsasl_encode (sctx, "foo", 3, &out, &outlen); if (res != GSASL_OK) fail ("gsasl_encode %d: %s\n", res, gsasl_strerror (res)); if (outlen != 3 && memcmp (out, "foo", outlen) != 0) fail ("gsasl_encode memcmp: %.*s\n", (int) outlen, out); gsasl_free (out); out = NULL; res = gsasl_decode (sctx, "foo", 3, &out, &outlen); if (res != GSASL_OK) fail ("gsasl_decode %d: %s\n", res, gsasl_strerror (res)); if (outlen != 3 && memcmp (out, "foo", outlen) != 0) fail ("gsasl_decode memcmp: %.*s\n", (int) outlen, out); gsasl_free (out); out = NULL; } gsasl_finish (sctx); if (debug) printf ("\n"); } gsasl_done (ctx); /* Sanity check interfaces. */ gsasl_finish (NULL); gsasl_done (NULL); }