static int cb_validate(Gsasl *ctx, Gsasl_session *sctx) { int rc; struct sasl_data *pdata = gsasl_callback_hook_get(ctx); const char *authid = gsasl_property_get(sctx, GSASL_AUTHID); const char *pass = gsasl_property_get(sctx, GSASL_PASSWORD); char *dbpass; if (!authid) return GSASL_NO_AUTHID; if (!pass) return GSASL_NO_PASSWORD; rc = dico_udb_check_password(user_db, authid, pass); if (rc == ENOSYS) { if (dico_udb_get_password(user_db, authid, &dbpass)) { dico_log(L_ERR, 0, _("failed to get password for `%s' from the database"), authid); return GSASL_AUTHENTICATION_ERROR; } rc = dicod_check_password(dbpass, pass); free(dbpass); } if (rc == 0) { pdata->username = xstrdup(authid); return GSASL_OK; } return GSASL_AUTHENTICATION_ERROR; }
// static int SASLSession::gsaslCallback (Gsasl* ctx, Gsasl_session* sctx, Gsasl_property prop) { SASLSession* sess = reinterpret_cast <SASLSession*>(gsasl_callback_hook_get(ctx)); if (!sess) return GSASL_AUTHENTICATION_ERROR; shared_ptr <authenticator> auth = sess->getAuthenticator(); try { string res; switch (prop) { case GSASL_AUTHID: res = auth->getUsername(); break; case GSASL_PASSWORD: res = auth->getPassword(); break; case GSASL_ANONYMOUS_TOKEN: res = auth->getAnonymousToken(); break; case GSASL_HOSTNAME: res = auth->getHostname(); break; case GSASL_SERVICE: res = auth->getServiceName(); break; case GSASL_AUTHZID: case GSASL_GSSAPI_DISPLAY_NAME: case GSASL_PASSCODE: case GSASL_SUGGESTED_PIN: case GSASL_PIN: case GSASL_REALM: default: return GSASL_NO_CALLBACK; } gsasl_property_set(sctx, prop, res.c_str()); return GSASL_OK; } catch (...) { return GSASL_NO_CALLBACK; } }
static int callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop) { int rc = GSASL_OK; struct sasl_data *pdata; const char *user; char *string; switch (prop) { case GSASL_PASSWORD: pdata = gsasl_callback_hook_get(ctx); user = pdata->username; if (!user) { user = gsasl_property_get(sctx, GSASL_AUTHID); if (!user) { dico_log(L_ERR, 0, _("user name not supplied")); return GSASL_NO_AUTHID; } pdata->username = user; } if (dico_udb_get_password(user_db, user, &string)) { dico_log(L_ERR, 0, _("failed to get password for `%s' from the database"), user); return GSASL_NO_PASSWORD; } gsasl_property_set(sctx, prop, string); free(string); break; case GSASL_SERVICE: gsasl_property_set(sctx, prop, sasl_service); break; case GSASL_REALM: gsasl_property_set(sctx, prop, sasl_realm ? sasl_realm : hostname); break; case GSASL_HOSTNAME: gsasl_property_set(sctx, prop, hostname); break; case GSASL_VALIDATE_SIMPLE: rc = cb_validate(ctx, sctx); break; #if 0 FIXME: case GSASL_VALIDATE_EXTERNAL: case GSASL_VALIDATE_SECURID: #endif case GSASL_VALIDATE_ANONYMOUS: pdata = gsasl_callback_hook_get(ctx); user = gsasl_property_get(sctx, GSASL_ANONYMOUS_TOKEN); pdata->username = user; pdata->anon = 1; break; case GSASL_VALIDATE_GSSAPI: pdata = gsasl_callback_hook_get(ctx); user = gsasl_property_get(sctx, GSASL_AUTHZID); pdata->username = user; break; default: rc = GSASL_NO_CALLBACK; /*dico_log(L_NOTICE, 0, _("Unsupported callback property %d"), prop);*/ break; } return rc; }
static int callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop) { int rc = GSASL_NO_CALLBACK; struct cfg *cfg = gsasl_callback_hook_get (ctx); switch (prop) { case GSASL_SAML20_REDIRECT_URL: { FILE *fh; char *reqid, *redirect_url, *tmp; size_t n = 0; const char *idp = gsasl_property_get (sctx, GSASL_SAML20_IDP_IDENTIFIER); /* User did not provide a SAML IdP identifier. */ if (!idp) return GSASL_AUTHENTICATION_ERROR; /* Sanitize input. */ if (strcmp (idp, ".") == 0 || strcmp (idp, "..") == 0) return GSASL_AUTHENTICATION_ERROR; for (n = 0; idp[n]; n++) if (!((idp[n] >= 'a' && idp[n] <= 'z') || (idp[n] >= 'A' && idp[n] <= 'Z') || (idp[n] >= '0' && idp[n] <= '9') || idp[n] == '.')) { printf ("Cannot handle identifier (%ld): %s\n", (unsigned long) n, idp); return GSASL_AUTHENTICATION_ERROR; } /* Run helper to generate SAML AuthnRequest. Read out request ID. */ rc = asprintf (&tmp, "gsasl-saml20-request %s %s %s %s " "%s/%s/idp-metadata.xml", cfg->state_path, cfg->sp_metadata, cfg->sp_key, cfg->sp_cert, cfg->cfg_path, idp); if (rc <= 0) return GSASL_AUTHENTICATION_ERROR; fh = popen (tmp, "r"); free (tmp); if (!fh) { perror ("popen"); return GSASL_AUTHENTICATION_ERROR; } reqid = NULL; n = 0; if (getline (&reqid, &n, fh) <= 0) { perror ("getline"); return GSASL_AUTHENTICATION_ERROR; } if (reqid[strlen (reqid) - 1] == '\n') reqid[strlen (reqid) - 1] = '\0'; if (reqid[strlen (reqid) - 1] == '\r') reqid[strlen (reqid) - 1] = '\0'; rc = pclose (fh); if (rc != 0) { perror ("pclose"); return GSASL_AUTHENTICATION_ERROR; } /* Read URL to redirect to. Written by gsasl-saml20-request. */ rc = asprintf (&tmp, "%s/%s/redirect_url", cfg->state_path, reqid); if (rc <= 0) return GSASL_AUTHENTICATION_ERROR; fh = fopen (tmp, "r"); free (tmp); if (!fh) { perror ("fopen"); return GSASL_AUTHENTICATION_ERROR; } redirect_url = NULL; n = 0; if (getline (&redirect_url, &n, fh) <= 0) { perror ("getline"); return GSASL_AUTHENTICATION_ERROR; } rc = fclose (fh); if (rc != 0) { perror ("fclose"); return GSASL_AUTHENTICATION_ERROR; } /* We are done */ gsasl_session_hook_set (sctx, reqid); gsasl_property_set (sctx, prop, redirect_url); printf ("read id: %s\n", reqid); printf ("url: %s\n", redirect_url); free (redirect_url); return GSASL_OK; } break; case GSASL_VALIDATE_SAML20: { time_t start = time (NULL); char *id = (char *) gsasl_session_hook_get (sctx); char *tmp, *line; size_t n; FILE *fh; if (!id) return GSASL_AUTHENTICATION_ERROR; do { sleep (1); rc = asprintf (&tmp, "%s/%s/success", cfg->state_path, id); if (rc <= 0) return GSASL_AUTHENTICATION_ERROR; fh = fopen (tmp, "r"); free (tmp); if (!fh) { rc = asprintf (&tmp, "%s/%s/fail", cfg->state_path, id); if (rc <= 0) return GSASL_AUTHENTICATION_ERROR; fh = fopen (tmp, "r"); free (tmp); if (!fh) { puts ("waiting"); continue; } rc = fclose (fh); if (rc != 0) { perror ("fclose"); return GSASL_AUTHENTICATION_ERROR; } return GSASL_AUTHENTICATION_ERROR; } rc = fclose (fh); if (rc != 0) { perror ("fclose"); return GSASL_AUTHENTICATION_ERROR; } rc = asprintf (&tmp, "%s/%s/subject", cfg->state_path, id); if (rc <= 0) return GSASL_AUTHENTICATION_ERROR; fh = fopen (tmp, "r"); free (tmp); if (!fh) { perror ("fopen"); return GSASL_AUTHENTICATION_ERROR; } line = NULL; n = 0; if (getline (&line, &n, fh) <= 0) { perror ("getline"); return GSASL_AUTHENTICATION_ERROR; } printf ("subject: %s\n", line); gsasl_property_set (sctx, GSASL_AUTHID, line); free (line); rc = fclose (fh); if (rc != 0) { perror ("fclose"); return GSASL_AUTHENTICATION_ERROR; } free (id); return GSASL_OK; } while (time (NULL) - start < 30); printf ("timeout\n"); return GSASL_AUTHENTICATION_ERROR; } break; case GSASL_PASSWORD: gsasl_property_set (sctx, prop, "sesam"); rc = GSASL_OK; break; default: /* You may want to log (at debug verbosity level) that an unknown property was requested here, possibly after filtering known rejected property requests. */ break; } return rc; }
static int cb (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop) { int rc = GSASL_NO_CALLBACK; int i = 0, j = 0; if (gsasl_callback_hook_get (ctx)) i = *(int *) gsasl_callback_hook_get (ctx); if (gsasl_session_hook_get (sctx)) j = *(int *) gsasl_session_hook_get (sctx); if (j < 0 || j > 5) fail ("j out of bounds: %d\n", j); switch (prop) { case GSASL_AUTHID: gsasl_property_set (sctx, prop, sasltv[i].authid); rc = GSASL_OK; break; case GSASL_AUTHZID: gsasl_property_set (sctx, prop, sasltv[i].authzid); rc = GSASL_OK; break; case GSASL_PASSWORD: gsasl_property_set (sctx, prop, sasltv[i].password); rc = GSASL_OK; break; case GSASL_ANONYMOUS_TOKEN: gsasl_property_set (sctx, prop, sasltv[i].anonymous); rc = GSASL_OK; break; case GSASL_SERVICE: rc = GSASL_OK; break; case GSASL_PASSCODE: gsasl_property_set (sctx, prop, sasltv[i].passcode); rc = GSASL_OK; break; case GSASL_SUGGESTED_PIN: case GSASL_PIN: { const char *suggestion = gsasl_property_fast (sctx, GSASL_SUGGESTED_PIN); if (suggestion && sasltv[i].suggestpin && strcmp (suggestion, sasltv[i].suggestpin) != 0) return GSASL_AUTHENTICATION_ERROR; if ((suggestion == NULL && sasltv[i].suggestpin != NULL) || (suggestion != NULL && sasltv[i].suggestpin == NULL)) return GSASL_AUTHENTICATION_ERROR; gsasl_property_set (sctx, prop, sasltv[i].pin); rc = GSASL_OK; } case GSASL_REALM: break; case GSASL_VALIDATE_EXTERNAL: rc = GSASL_OK; break; case GSASL_VALIDATE_ANONYMOUS: if (strcmp (sasltv[i].anonymous, gsasl_property_fast (sctx, GSASL_ANONYMOUS_TOKEN)) == 0) rc = GSASL_OK; else rc = GSASL_AUTHENTICATION_ERROR; break; case GSASL_VALIDATE_SECURID: { const char *passcode = gsasl_property_fast (sctx, GSASL_PASSCODE); const char *pin = gsasl_property_fast (sctx, GSASL_PIN); if (strcmp (passcode, sasltv[i].passcode) != 0) return GSASL_AUTHENTICATION_ERROR; if (sasltv[i].securidrc == GSASL_SECURID_SERVER_NEED_NEW_PIN) { rc = sasltv[i].securidrc; sasltv[i].securidrc = GSASL_OK; if (sasltv[i].suggestpin) { gsasl_property_set (sctx, GSASL_SUGGESTED_PIN, sasltv[i].suggestpin); } } else if (sasltv[i].securidrc == GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE) { rc = sasltv[i].securidrc; sasltv[i].securidrc = GSASL_OK; } else { rc = sasltv[i].securidrc; if (pin && sasltv[i].pin && strcmp (pin, sasltv[i].pin) != 0) return GSASL_AUTHENTICATION_ERROR; if ((pin == NULL && sasltv[i].pin != NULL) || (pin != NULL && sasltv[i].pin == NULL)) return GSASL_AUTHENTICATION_ERROR; } } break; default: printf ("Unknown property %d\n", prop); break; } return rc; }