int capabilities(struct protstream *conn, sasl_conn_t *saslconn, int starttls_done, int authenticated, sasl_ssf_t sasl_ssf) { const char *sasllist; int mechcount; /* implementation */ prot_printf(conn, "\"IMPLEMENTATION\" \"Cyrus timsieved%s %s\"\r\n", config_mupdate_server ? " (Murder)" : "", cyrus_version()); /* SASL */ if ((!authenticated || sasl_ssf) && sasl_listmech(saslconn, NULL, "\"SASL\" \"", " ", "\"\r\n", &sasllist, NULL, &mechcount) == SASL_OK/* && mechcount > 0*/) { prot_printf(conn,"%s",sasllist); } /* Sieve capabilities */ prot_printf(conn,"\"SIEVE\" \"%s\"\r\n",sieve_listextensions(interp)); if (tls_enabled() && !starttls_done && !authenticated) { prot_printf(conn, "\"STARTTLS\"\r\n"); } prot_printf(conn,"OK\r\n"); return TIMSIEVE_OK; }
char *virNetSASLSessionListMechanisms(virNetSASLSessionPtr sasl) { const char *mechlist; char *ret = NULL; int err; virObjectLock(sasl); err = sasl_listmech(sasl->conn, NULL, /* Don't need to set user */ "", /* Prefix */ ",", /* Separator */ "", /* Suffix */ &mechlist, NULL, NULL); if (err != SASL_OK) { virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot list SASL mechanisms %d (%s)"), err, sasl_errdetail(sasl->conn)); goto cleanup; } ignore_value(VIR_STRDUP(ret, mechlist)); cleanup: virObjectUnlock(sasl); return ret; }
char *virNetSASLSessionListMechanisms(virNetSASLSessionPtr sasl) { const char *mechlist; char *ret = NULL; int err; virMutexLock(&sasl->lock); err = sasl_listmech(sasl->conn, NULL, /* Don't need to set user */ "", /* Prefix */ ",", /* Separator */ "", /* Suffix */ &mechlist, NULL, NULL); if (err != SASL_OK) { virNetError(VIR_ERR_INTERNAL_ERROR, _("cannot list SASL mechanisms %d (%s)"), err, sasl_errdetail(sasl->conn)); goto cleanup; } if (!(ret = strdup(mechlist))) { virReportOOMError(); goto cleanup; } cleanup: virMutexUnlock(&sasl->lock); return ret; }
static const char *xsasl_cyrus_server_get_mechanism_list(XSASL_SERVER *xp) { const char *myname = "xsasl_cyrus_server_get_mechanism_list"; XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp; MECHANISM_TYPE mechanism_list; MECHANISM_COUNT_TYPE mechanism_count; int sasl_status; /* * Get the list of authentication mechanisms. */ #define UNSUPPORTED_USER ((char *) 0) #define IGNORE_MECHANISM_LEN ((unsigned *) 0) if ((sasl_status = sasl_listmech(server->sasl_conn, UNSUPPORTED_USER, "", " ", "", &mechanism_list, IGNORE_MECHANISM_LEN, &mechanism_count)) != SASL_OK) { msg_warn("%s: %s", myname, xsasl_cyrus_strerror(sasl_status)); return (0); } if (mechanism_count <= 0) { msg_warn("%s: no applicable SASL mechanisms", myname); return (0); } server->mechanism_list = mystrdup(mechanism_list); #if SASL_VERSION_MAJOR < 2 /* SASL version 1 doesn't free memory that it allocates. */ free(mechanism_list); #endif return (server->mechanism_list); }
int pni_sasl_impl_list_mechs(pn_transport_t *transport, char **mechlist) { pni_sasl_t *sasl = transport->sasl; sasl_conn_t *cyrus_conn = (sasl_conn_t*)sasl->impl_context; int count = 0; if (cyrus_conn) { const char *result = NULL; int r = sasl_listmech(cyrus_conn, NULL, "", " ", "", &result, NULL, &count); if (pni_check_sasl_result(cyrus_conn, r, transport)) { if (result && *result) { *mechlist = pn_strdup(result); } } } return count; }
/* mechslist = cyrussasl.listmech(conn, authid, prefix, separator, suffix) * * Return all of the available mechanisms to the Cyrus SASL library. * * conn: the conn pointer from cyrussasl.server_new(). * authid: the username trying to authenticate. May be nil. * prefix: prefix to prepend to the returned string. May be an empty string. * separator: the string to use to separate mechanisms. May be empty. * suffix: suffix to postpend to the returned string. May be empty. * * mechslist: a Lua string object containing the mechanisms (GSSAPI, et al) */ static int cyrussasl_sasl_listmech(lua_State *l) { int err; struct _sasl_ctx *ctx = NULL; const char *ext_authid = NULL; const char *data = NULL; const char *prefix = NULL; const char *separator = NULL; const char *suffix = NULL; unsigned len; int count; int numargs = lua_gettop(l); if (numargs != 5) { lua_pushstring(l, "usage: " "mechslist = cyrussasl.listmech" "(conn, authid, prefix, separator, suffix)"); lua_error(l); return 0; } ctx = get_context(l, 1); ext_authid = tostring(l, 2); prefix = tostring(l, 3); separator = tostring(l, 4); suffix = tostring(l, 5); err = sasl_listmech(ctx->conn, ext_authid, prefix, separator, suffix, &data, &len, &count); if ( err != SASL_OK ) { lua_pushstring(l, "sasl_listmech failed"); lua_error(l); return 0; } lua_pushlstring(l, data, len); return 1; }
bool serverStart(const QString &realm, QStringList *mechlist, const QString &name) { resetState(); g->appname = name; if(!g->server_init) { sasl_server_init(NULL, QFile::encodeName(g->appname)); g->server_init = true; } callbacks = new sasl_callback_t[2]; callbacks[0].id = SASL_CB_PROXY_POLICY; callbacks[0].proc = (int(*)())scb_checkauth; callbacks[0].context = this; callbacks[1].id = SASL_CB_LIST_END; callbacks[1].proc = 0; callbacks[1].context = 0; int r = sasl_server_new(service.toLatin1().data(), host.toLatin1().data(), realm.toLatin1().data(), localAddr.isEmpty() ? 0 : localAddr.toLatin1().data(), remoteAddr.isEmpty() ? 0 : remoteAddr.toLatin1().data(), callbacks, 0, &con); if(r != SASL_OK) { err = saslErrorCond(r); return false; } if(!setsecprops()) return false; const char *ml; r = sasl_listmech(con, 0, NULL, " ", NULL, &ml, 0, 0); if(r != SASL_OK) return false; *mechlist = QString(ml).split(' ', QString::SkipEmptyParts); servermode = true; step = 0; ca_done = false; ca_skip = false; return true; }
static int __pmAuthServerNegotiation(int fd, int ssf, __pmHashCtl *attrs) { int sts, saslsts; int pinned, length, count; char *payload, *offset; sasl_conn_t *sasl_conn; __pmPDU *pb; if (pmDebugOptions.auth) fprintf(stderr, "__pmAuthServerNegotiation(fd=%d, ssf=%d)\n", fd, ssf); if ((sasl_conn = (sasl_conn_t *)__pmGetUserAuthData(fd)) == NULL) return -EINVAL; /* setup all the security properties for this connection */ if ((sts = __pmAuthServerSetProperties(sasl_conn, ssf)) < 0) return sts; saslsts = sasl_listmech(sasl_conn, NULL, NULL, " ", NULL, (const char **)&payload, (unsigned int *)&length, &count); if (saslsts != SASL_OK && saslsts != SASL_CONTINUE) { pmNotifyErr(LOG_ERR, "Generating client mechanism list: %s", sasl_errstring(saslsts, NULL, NULL)); return __pmSecureSocketsError(saslsts); } if (pmDebugOptions.auth) fprintf(stderr, "__pmAuthServerNegotiation - sending mechanism list " "(%d items, %d bytes): \"%s\"\n", count, length, payload); if ((sts = __pmSendAuth(fd, FROM_ANON, 0, payload, length)) < 0) return sts; if (pmDebugOptions.auth) fprintf(stderr, "__pmAuthServerNegotiation - wait for mechanism\n"); sts = pinned = __pmGetPDU(fd, ANY_SIZE, TIMEOUT_DEFAULT, &pb); if (sts == PDU_AUTH) { sts = __pmDecodeAuth(pb, &count, &payload, &length); if (sts >= 0) { for (count = 0; count < length; count++) { if (payload[count] == '\0') break; } if (count < length) { /* found an initial response */ length = length - count - 1; offset = payload + count + 1; } else { length = 0; offset = NULL; } saslsts = sasl_server_start(sasl_conn, payload, offset, length, (const char **)&payload, (unsigned int *)&length); if (saslsts != SASL_OK && saslsts != SASL_CONTINUE) { sts = __pmSecureSocketsError(saslsts); if (pmDebugOptions.auth) fprintf(stderr, "sasl_server_start failed: %d (%s)\n", saslsts, pmErrStr(sts)); } else { if (pmDebugOptions.auth) fprintf(stderr, "sasl_server_start success: sts=%s\n", saslsts == SASL_CONTINUE ? "continue" : "ok"); } } } else if (sts == PDU_ERROR) __pmDecodeError(pb, &sts); else if (sts != PM_ERR_TIMEOUT) sts = PM_ERR_IPC; if (pinned > 0) __pmUnpinPDUBuf(pb); if (sts < 0) return sts; if (pmDebugOptions.auth) fprintf(stderr, "__pmAuthServerNegotiation method negotiated\n"); while (saslsts == SASL_CONTINUE) { if (!payload) { pmNotifyErr(LOG_ERR, "No SASL data to send"); sts = -EINVAL; break; } if ((sts = __pmSendAuth(fd, FROM_ANON, 0, payload, length)) < 0) break; if (pmDebugOptions.auth) fprintf(stderr, "__pmAuthServerNegotiation awaiting response\n"); sts = pinned = __pmGetPDU(fd, ANY_SIZE, TIMEOUT_DEFAULT, &pb); if (sts == PDU_AUTH) { sts = __pmDecodeAuth(pb, &count, &payload, &length); if (sts >= 0) { sts = saslsts = sasl_server_step(sasl_conn, payload, length, (const char **)&payload, (unsigned int *)&length); if (sts != SASL_OK && sts != SASL_CONTINUE) { sts = __pmSecureSocketsError(sts); break; } if (pmDebugOptions.auth) { fprintf(stderr, "__pmAuthServerNegotiation" " step recv (%d bytes)\n", length); } } } else if (sts == PDU_ERROR) __pmDecodeError(pb, &sts); else if (sts != PM_ERR_TIMEOUT) sts = PM_ERR_IPC; if (pinned > 0) __pmUnpinPDUBuf(pb); if (sts < 0) break; } if (sts < 0) { if (pmDebugOptions.auth) fprintf(stderr, "__pmAuthServerNegotiation loop failed: %d\n", sts); return sts; } return __pmAuthServerSetAttributes(sasl_conn, attrs); }
void auth_cyrus_sasl_init(auth_instance *ablock) { auth_cyrus_sasl_options_block *ob = (auth_cyrus_sasl_options_block *)(ablock->options_block); const uschar *list, *listptr, *buffer; int rc, i; unsigned int len; uschar *rs_point, *expanded_hostname; char *realm_expanded; sasl_conn_t *conn; sasl_callback_t cbs[] = { {SASL_CB_GETOPT, NULL, NULL }, {SASL_CB_LIST_END, NULL, NULL}}; /* default the mechanism to our "public name" */ if (ob->server_mech == NULL) ob->server_mech = string_copy(ablock->public_name); expanded_hostname = expand_string(ob->server_hostname); if (expanded_hostname == NULL) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "couldn't expand server_hostname [%s]: %s", ablock->name, ob->server_hostname, expand_string_message); realm_expanded = NULL; if (ob->server_realm != NULL) { realm_expanded = CS expand_string(ob->server_realm); if (realm_expanded == NULL) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "couldn't expand server_realm [%s]: %s", ablock->name, ob->server_realm, expand_string_message); } /* we're going to initialise the library to check that there is an * authenticator of type whatever mechanism we're using */ cbs[0].proc = (int(*)(void)) &mysasl_config; cbs[0].context = ob->server_mech; if ((rc = sasl_server_init(cbs, "exim")) != SASL_OK ) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "couldn't initialise Cyrus SASL library.", ablock->name); if ((rc = sasl_server_new(CS ob->server_service, CS expanded_hostname, realm_expanded, NULL, NULL, NULL, 0, &conn)) != SASL_OK ) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "couldn't initialise Cyrus SASL server connection.", ablock->name); if ((rc = sasl_listmech(conn, NULL, "", ":", "", (const char **)&list, &len, &i)) != SASL_OK ) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "couldn't get Cyrus SASL mechanism list.", ablock->name); i = ':'; listptr = list; HDEBUG(D_auth) { debug_printf("Initialised Cyrus SASL service=\"%s\" fqdn=\"%s\" realm=\"%s\"\n", ob->server_service, expanded_hostname, realm_expanded); debug_printf("Cyrus SASL knows mechanisms: %s\n", list); } /* the store_get / store_reset mechanism is hierarchical * the hierarchy is stored for us behind our back. This point * creates a hierarchy point for this function. */ rs_point = store_get(0); /* loop until either we get to the end of the list, or we match the * public name of this authenticator */ while ( ( buffer = string_nextinlist(&listptr, &i, NULL, 0) ) && strcmpic(buffer,ob->server_mech) ); if (!buffer) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s authenticator: " "Cyrus SASL doesn't know about mechanism %s.", ablock->name, ob->server_mech); store_reset(rs_point); HDEBUG(D_auth) debug_printf("Cyrus SASL driver %s: %s initialised\n", ablock->name, ablock->public_name); /* make sure that if we get here then we're allowed to advertise. */ ablock->server = TRUE; sasl_dispose(&conn); sasl_done(); }
/* do the sasl negotiation; return -1 if it fails */ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) { char buf[8192]; char chosenmech[128]; const char *data; int len; int r = SASL_FAIL; const char *userid; #ifdef HAVE_GSS_GET_NAME_ATTRIBUTE gss_name_t peer = GSS_C_NO_NAME; #endif /* generate the capability list */ if (mech) { dprintf(2, "forcing use of mechanism %s\n", mech); data = strdup(mech); len = strlen(data); } else { int count; dprintf(1, "generating client mechanism list... "); r = sasl_listmech(conn, NULL, NULL, " ", NULL, &data, (unsigned int *)&len, &count); if (r != SASL_OK) saslfail(r, "generating mechanism list"); dprintf(1, "%d mechanisms\n", count); } /* send capability list to client */ send_string(out, data, len); dprintf(1, "waiting for client mechanism...\n"); len = recv_string(in, chosenmech, sizeof chosenmech); if (len <= 0) { printf("client didn't choose mechanism\n"); fputc('N', out); /* send NO to client */ fflush(out); return -1; } if (mech && strcasecmp(mech, chosenmech)) { printf("client didn't choose mandatory mechanism\n"); fputc('N', out); /* send NO to client */ fflush(out); return -1; } len = recv_string(in, buf, sizeof(buf)); if(len != 1) { saslerr(r, "didn't receive first-send parameter correctly"); fprintf(stderr, "%s\n", sasl_errdetail(conn)); fputc('N', out); fflush(out); return -1; } if(buf[0] == 'Y') { /* receive initial response (if any) */ len = recv_string(in, buf, sizeof(buf)); /* start libsasl negotiation */ r = sasl_server_start(conn, chosenmech, buf, len, &data, (unsigned int *)&len); } else { r = sasl_server_start(conn, chosenmech, NULL, 0, &data, (unsigned int *)&len); } if (r != SASL_OK && r != SASL_CONTINUE) { saslerr(r, "starting SASL negotiation"); fprintf(stderr, "%s\n", sasl_errdetail(conn)); fputc('N', out); /* send NO to client */ fflush(out); return -1; } while (r == SASL_CONTINUE) { if (data) { dprintf(2, "sending response length %d...\n", len); fputc('C', out); /* send CONTINUE to client */ send_string(out, data, len); } else { dprintf(2, "sending null response...\n"); fputc('C', out); /* send CONTINUE to client */ send_string(out, "", 0); } dprintf(1, "waiting for client reply...\n"); len = recv_string(in, buf, sizeof buf); if (len < 0) { printf("client disconnected\n"); return -1; } r = sasl_server_step(conn, buf, len, &data, (unsigned int *)&len); if (r != SASL_OK && r != SASL_CONTINUE) { saslerr(r, "performing SASL negotiation"); fprintf(stderr, "%s\n", sasl_errdetail(conn)); fputc('N', out); /* send NO to client */ fflush(out); return -1; } } if (r != SASL_OK) { saslerr(r, "incorrect authentication"); fprintf(stderr, "%s\n", sasl_errdetail(conn)); fputc('N', out); /* send NO to client */ fflush(out); return -1; } fputc('O', out); /* send OK to client */ fflush(out); dprintf(1, "negotiation complete\n"); r = sasl_getprop(conn, SASL_USERNAME, (const void **) &userid); printf("successful authentication '%s'\n", userid); #ifdef HAVE_GSS_GET_NAME_ATTRIBUTE r = sasl_getprop(conn, SASL_GSS_PEER_NAME, (const void **) &peer); if (peer != GSS_C_NO_NAME) { OM_uint32 minor; enumerateAttributes(&minor, peer, 1); } #endif return 0; }
/** * Initialize and start SASL authentication. * * Returns 0 on successful init and -1 on error. * * Locality: broker thread */ int rd_kafka_sasl_client_new (rd_kafka_transport_t *rktrans, char *errstr, int errstr_size) { int r; rd_kafka_broker_t *rkb = rktrans->rktrans_rkb; rd_kafka_t *rk = rkb->rkb_rk; char *hostname, *t; sasl_callback_t callbacks[16] = { // { SASL_CB_GETOPT, (void *)rd_kafka_sasl_cb_getopt, rktrans }, { SASL_CB_LOG, (void *)rd_kafka_sasl_cb_log, rktrans }, { SASL_CB_AUTHNAME, (void *)rd_kafka_sasl_cb_getsimple, rktrans }, { SASL_CB_PASS, (void *)rd_kafka_sasl_cb_getsecret, rktrans }, { SASL_CB_ECHOPROMPT, (void *)rd_kafka_sasl_cb_chalprompt, rktrans }, { SASL_CB_GETREALM, (void *)rd_kafka_sasl_cb_getrealm, rktrans }, { SASL_CB_CANON_USER, (void *)rd_kafka_sasl_cb_canon, rktrans }, { SASL_CB_LIST_END } }; /* SASL_CB_USER is needed for PLAIN but breaks GSSAPI */ if (!strcmp(rk->rk_conf.sasl.service_name, "PLAIN")) { int endidx; /* Find end of callbacks array */ for (endidx = 0 ; callbacks[endidx].id != SASL_CB_LIST_END ; endidx++) ; callbacks[endidx].id = SASL_CB_USER; callbacks[endidx].proc = (void *)rd_kafka_sasl_cb_getsimple; endidx++; callbacks[endidx].id = SASL_CB_LIST_END; } rd_strdupa(&hostname, rktrans->rktrans_rkb->rkb_nodename); if ((t = strchr(hostname, ':'))) *t = '\0'; /* remove ":port" */ rd_rkb_dbg(rkb, SECURITY, "SASL", "Initializing SASL client: service name %s, " "hostname %s, mechanisms %s", rk->rk_conf.sasl.service_name, hostname, rk->rk_conf.sasl.mechanisms); /* Acquire or refresh ticket if kinit is configured */ rd_kafka_sasl_kinit_refresh(rkb); r = sasl_client_new(rk->rk_conf.sasl.service_name, hostname, NULL, NULL, /* no local & remote IP checks */ callbacks, 0, &rktrans->rktrans_sasl.conn); if (r != SASL_OK) { rd_snprintf(errstr, errstr_size, "%s", sasl_errstring(r, NULL, NULL)); return -1; } if (rk->rk_conf.debug & RD_KAFKA_DBG_SECURITY) { const char *avail_mechs; sasl_listmech(rktrans->rktrans_sasl.conn, NULL, NULL, " ", NULL, &avail_mechs, NULL, NULL); rd_rkb_dbg(rkb, SECURITY, "SASL", "My supported SASL mechanisms: %s", avail_mechs); } rd_kafka_transport_poll_set(rktrans, POLLIN); do { const char *out; unsigned int outlen; const char *mech = NULL; r = sasl_client_start(rktrans->rktrans_sasl.conn, rk->rk_conf.sasl.mechanisms, NULL, &out, &outlen, &mech); if (r >= 0) if (rd_kafka_sasl_send(rktrans, out, outlen, errstr, errstr_size)) return -1; } while (r == SASL_INTERACT); if (r == SASL_OK) { /* PLAIN is appearantly done here, but we still need to make sure * the PLAIN frame is sent and we get a response back (but we must * not pass the response to libsasl or it will fail). */ rktrans->rktrans_sasl.complete = 1; return 0; } else if (r != SASL_CONTINUE) { rd_snprintf(errstr, errstr_size, "SASL handshake failed (start (%d)): %s", r, sasl_errdetail(rktrans->rktrans_sasl.conn)); return -1; } return 0; }
svn_error_t *cyrus_auth_request(svn_ra_svn_conn_t *conn, apr_pool_t *pool, server_baton_t *b, enum access_type required, svn_boolean_t needs_username) { sasl_conn_t *sasl_ctx; apr_pool_t *subpool; apr_status_t apr_err; const char *localaddrport = NULL, *remoteaddrport = NULL; const char *mechlist, *val; char hostname[APRMAXHOSTLEN + 1]; sasl_security_properties_t secprops; svn_boolean_t success, no_anonymous; int mech_count, result = SASL_OK; SVN_ERR(svn_ra_svn__get_addresses(&localaddrport, &remoteaddrport, conn, pool)); apr_err = apr_gethostname(hostname, sizeof(hostname), pool); if (apr_err) { svn_error_t *err = svn_error_wrap_apr(apr_err, _("Can't get hostname")); SVN_ERR(write_failure(conn, pool, &err)); return svn_ra_svn_flush(conn, pool); } /* Create a SASL context. SASL_SUCCESS_DATA tells SASL that the protocol supports sending data along with the final "success" message. */ result = sasl_server_new(SVN_RA_SVN_SASL_NAME, hostname, b->realm, localaddrport, remoteaddrport, NULL, SASL_SUCCESS_DATA, &sasl_ctx); if (result != SASL_OK) { svn_error_t *err = svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, sasl_errstring(result, NULL, NULL)); SVN_ERR(write_failure(conn, pool, &err)); return svn_ra_svn_flush(conn, pool); } /* Make sure the context is always destroyed. */ apr_pool_cleanup_register(b->pool, sasl_ctx, sasl_dispose_cb, apr_pool_cleanup_null); /* Initialize security properties. */ svn_ra_svn__default_secprops(&secprops); /* Don't allow ANONYMOUS if a username is required. */ no_anonymous = needs_username || get_access(b, UNAUTHENTICATED) < required; if (no_anonymous) secprops.security_flags |= SASL_SEC_NOANONYMOUS; svn_config_get(b->cfg, &val, SVN_CONFIG_SECTION_SASL, SVN_CONFIG_OPTION_MIN_SSF, "0"); SVN_ERR(svn_cstring_atoui(&secprops.min_ssf, val)); svn_config_get(b->cfg, &val, SVN_CONFIG_SECTION_SASL, SVN_CONFIG_OPTION_MAX_SSF, "256"); SVN_ERR(svn_cstring_atoui(&secprops.max_ssf, val)); /* Set security properties. */ result = sasl_setprop(sasl_ctx, SASL_SEC_PROPS, &secprops); if (result != SASL_OK) return fail_cmd(conn, pool, sasl_ctx); /* SASL needs to know if we are externally authenticated. */ if (b->tunnel_user) result = sasl_setprop(sasl_ctx, SASL_AUTH_EXTERNAL, b->tunnel_user); if (result != SASL_OK) return fail_cmd(conn, pool, sasl_ctx); /* Get the list of mechanisms. */ result = sasl_listmech(sasl_ctx, NULL, NULL, " ", NULL, &mechlist, NULL, &mech_count); if (result != SASL_OK) return fail_cmd(conn, pool, sasl_ctx); if (mech_count == 0) { svn_error_t *err = svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, _("Could not obtain the list" " of SASL mechanisms")); SVN_ERR(write_failure(conn, pool, &err)); return svn_ra_svn_flush(conn, pool); } /* Send the list of mechanisms and the realm to the client. */ SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "(w)c", mechlist, b->realm)); /* The main authentication loop. */ subpool = svn_pool_create(pool); do { svn_pool_clear(subpool); SVN_ERR(try_auth(conn, sasl_ctx, subpool, b, &success)); } while (!success); svn_pool_destroy(subpool); SVN_ERR(svn_ra_svn__enable_sasl_encryption(conn, sasl_ctx, pool)); if (no_anonymous) { char *p; const void *user; /* Get the authenticated username. */ result = sasl_getprop(sasl_ctx, SASL_USERNAME, &user); if (result != SASL_OK) return fail_cmd(conn, pool, sasl_ctx); if ((p = strchr(user, '@')) != NULL) { /* Drop the realm part. */ b->user = apr_pstrndup(b->pool, user, p - (const char *)user); } else { svn_error_t *err; err = svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, _("Couldn't obtain the authenticated" " username")); SVN_ERR(write_failure(conn, pool, &err)); return svn_ra_svn_flush(conn, pool); } } return SVN_NO_ERROR; }
bool reds_sasl_start_auth(RedsStream *stream, AsyncReadDone read_cb, void *opaque) { const char *mechlist = NULL; sasl_security_properties_t secprops; int err; char *localAddr, *remoteAddr; int mechlistlen; RedsSASL *sasl = &stream->priv->sasl; if (!(localAddr = reds_stream_get_local_address(stream))) { goto error; } if (!(remoteAddr = reds_stream_get_remote_address(stream))) { free(localAddr); goto error; } err = sasl_server_new("spice", NULL, /* FQDN - just delegates to gethostname */ NULL, /* User realm */ localAddr, remoteAddr, NULL, /* Callbacks, not needed */ SASL_SUCCESS_DATA, &sasl->conn); free(localAddr); free(remoteAddr); localAddr = remoteAddr = NULL; if (err != SASL_OK) { spice_warning("sasl context setup failed %d (%s)", err, sasl_errstring(err, NULL, NULL)); sasl->conn = NULL; goto error; } /* Inform SASL that we've got an external SSF layer from TLS */ if (stream->priv->ssl) { sasl_ssf_t ssf; ssf = SSL_get_cipher_bits(stream->priv->ssl, NULL); err = sasl_setprop(sasl->conn, SASL_SSF_EXTERNAL, &ssf); if (err != SASL_OK) { spice_warning("cannot set SASL external SSF %d (%s)", err, sasl_errstring(err, NULL, NULL)); goto error_dispose; } } else { sasl->wantSSF = 1; } memset(&secprops, 0, sizeof secprops); /* Inform SASL that we've got an external SSF layer from TLS */ if (stream->priv->ssl) { /* If we've got TLS (or UNIX domain sock), we don't care about SSF */ secprops.min_ssf = 0; secprops.max_ssf = 0; secprops.maxbufsize = 8192; secprops.security_flags = 0; } else { /* Plain TCP, better get an SSF layer */ secprops.min_ssf = 56; /* Good enough to require kerberos */ secprops.max_ssf = 100000; /* Arbitrary big number */ secprops.maxbufsize = 8192; /* Forbid any anonymous or trivially crackable auth */ secprops.security_flags = SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT; } err = sasl_setprop(sasl->conn, SASL_SEC_PROPS, &secprops); if (err != SASL_OK) { spice_warning("cannot set SASL security props %d (%s)", err, sasl_errstring(err, NULL, NULL)); goto error_dispose; } err = sasl_listmech(sasl->conn, NULL, /* Don't need to set user */ "", /* Prefix */ ",", /* Separator */ "", /* Suffix */ &mechlist, NULL, NULL); if (err != SASL_OK || mechlist == NULL) { spice_warning("cannot list SASL mechanisms %d (%s)", err, sasl_errdetail(sasl->conn)); goto error_dispose; } spice_debug("Available mechanisms for client: '%s'", mechlist); sasl->mechlist = spice_strdup(mechlist); mechlistlen = strlen(mechlist); if (!reds_stream_write_all(stream, &mechlistlen, sizeof(uint32_t)) || !reds_stream_write_all(stream, sasl->mechlist, mechlistlen)) { spice_warning("SASL mechanisms write error"); goto error; } spice_debug("Wait for client mechname length"); reds_stream_async_read(stream, (uint8_t *)&sasl->len, sizeof(uint32_t), read_cb, opaque); return true; error_dispose: sasl_dispose(&sasl->conn); sasl->conn = NULL; error: return false; }
int ArgusAuthenticateClient (struct ArgusClientData *client) { int retn = 1; #ifdef ARGUS_SASL unsigned int rlen = 0; int len, mechnum = 0; char buf[8192], chosenmech[512]; const char *data; sasl_conn_t *conn = NULL; // int SASLOpts = (SASL_SEC_NOPLAINTEXT | SASL_SEC_NOANONYMOUS); FILE *in, *out; conn = client->sasl_conn; if ((retn = sasl_listmech(conn, NULL, "{", ", ", "}", &data, &rlen, &mechnum)) != SASL_OK) ArgusLog (LOG_ERR, "ArgusAuthenticateClient: Error generating mechanism list"); if ((in = fdopen (client->fd, "r")) < 0) ArgusLog (LOG_ERR, "ArgusAuthenticateClient: fdopen() error %s", strerror(errno)); if ((out = fdopen (client->fd, "w")) < 0) ArgusLog (LOG_ERR, "ArgusAuthenticateClient: fdopen() error %s", strerror(errno)); ArgusSendSaslString (out, data, rlen, SASL_OK); if ((len = ArgusGetSaslString (in, chosenmech, sizeof(chosenmech))) <= 0) { #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusAuthenticateClient: Error ArgusGetSaslString returned %d\n", len); #endif return 0; } if ((len = ArgusGetSaslString (in, buf, sizeof(buf))) <= 0) { #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusAuthenticateClient: Error ArgusGetSaslString returned %d\n", len); #endif return 0; } if (*buf == 'Y') { if ((len = ArgusGetSaslString (in, buf, sizeof(buf))) <= 0) { #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusAuthenticateClient: Error ArgusGetSaslString returned %d\n", len); #endif return 0; } retn = sasl_server_start(conn, chosenmech, buf, len, &data, &rlen); } else { retn = sasl_server_start(conn, chosenmech, NULL, 0, &data, &rlen); } if ((retn != SASL_OK) && (retn != SASL_CONTINUE)) { sprintf (buf, "%s", sasl_errstring(retn, NULL, NULL)); #ifdef ARGUSDEBUG ArgusDebug (2, "ArgusAuthenticateClient: Error starting SASL negotiation"); #endif ArgusSendSaslString(out, buf, strlen(buf), retn); return 0; } while (retn == SASL_CONTINUE) { if (data) { #ifdef ARGUSDEBUG ArgusDebug(2, "sending response length %d...\n", rlen); #endif ArgusSendSaslString(out, data, rlen, retn); } else { #ifdef ARGUSDEBUG ArgusDebug(2, "no data to send? ...\n"); #endif } #ifdef ARGUSDEBUG ArgusDebug(2, "waiting for client reply...\n"); #endif len = ArgusGetSaslString(in, buf, sizeof(buf)); if (len < 0) { #ifdef ARGUSDEBUG ArgusDebug(2, "client disconnected ...\n"); #endif return 0; } retn = sasl_server_step(conn, buf, len, &data, &rlen); if ((retn != SASL_OK) && (retn != SASL_CONTINUE)) { sprintf (buf, "%s", sasl_errstring(retn, NULL, NULL)); #ifdef ARGUSDEBUG ArgusDebug(2, "Authentication failed %s\n", sasl_errstring(retn, NULL, NULL)); #endif ArgusSendSaslString(out, buf, strlen(buf), retn); return 0; } } if (retn == SASL_OK) ArgusSendSaslString(out, NULL, 0, SASL_OK); #endif #ifdef ARGUSDEBUG ArgusDebug (1, "ArgusAuthenticateClient() returning %d\n", retn); #endif return (retn); }
void start_auth_sasl(VncState *vs) { const char *mechlist = NULL; sasl_security_properties_t secprops; int err; char *localAddr, *remoteAddr; int mechlistlen; VNC_DEBUG("Initialize SASL auth %p\n", vs->ioc); /* Get local & remote client addresses in form IPADDR;PORT */ localAddr = vnc_socket_ip_addr_string(vs->sioc, true, NULL); if (!localAddr) { goto authabort; } remoteAddr = vnc_socket_ip_addr_string(vs->sioc, false, NULL); if (!remoteAddr) { g_free(localAddr); goto authabort; } err = sasl_server_new("vnc", NULL, /* FQDN - just delegates to gethostname */ NULL, /* User realm */ localAddr, remoteAddr, NULL, /* Callbacks, not needed */ SASL_SUCCESS_DATA, &vs->sasl.conn); g_free(localAddr); g_free(remoteAddr); localAddr = remoteAddr = NULL; if (err != SASL_OK) { VNC_DEBUG("sasl context setup failed %d (%s)", err, sasl_errstring(err, NULL, NULL)); vs->sasl.conn = NULL; goto authabort; } /* Inform SASL that we've got an external SSF layer from TLS/x509 */ if (vs->auth == VNC_AUTH_VENCRYPT && vs->subauth == VNC_AUTH_VENCRYPT_X509SASL) { Error *local_err = NULL; int keysize; sasl_ssf_t ssf; keysize = qcrypto_tls_session_get_key_size(vs->tls, &local_err); if (keysize < 0) { VNC_DEBUG("cannot TLS get cipher size: %s\n", error_get_pretty(local_err)); error_free(local_err); sasl_dispose(&vs->sasl.conn); vs->sasl.conn = NULL; goto authabort; } ssf = keysize * CHAR_BIT; /* tls key size is bytes, sasl wants bits */ err = sasl_setprop(vs->sasl.conn, SASL_SSF_EXTERNAL, &ssf); if (err != SASL_OK) { VNC_DEBUG("cannot set SASL external SSF %d (%s)\n", err, sasl_errstring(err, NULL, NULL)); sasl_dispose(&vs->sasl.conn); vs->sasl.conn = NULL; goto authabort; } } else { vs->sasl.wantSSF = 1; } memset (&secprops, 0, sizeof secprops); /* Inform SASL that we've got an external SSF layer from TLS. * * Disable SSF, if using TLS+x509+SASL only. TLS without x509 * is not sufficiently strong */ if (vs->vd->is_unix || (vs->auth == VNC_AUTH_VENCRYPT && vs->subauth == VNC_AUTH_VENCRYPT_X509SASL)) { /* If we've got TLS or UNIX domain sock, we don't care about SSF */ secprops.min_ssf = 0; secprops.max_ssf = 0; secprops.maxbufsize = 8192; secprops.security_flags = 0; } else { /* Plain TCP, better get an SSF layer */ secprops.min_ssf = 56; /* Good enough to require kerberos */ secprops.max_ssf = 100000; /* Arbitrary big number */ secprops.maxbufsize = 8192; /* Forbid any anonymous or trivially crackable auth */ secprops.security_flags = SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT; } err = sasl_setprop(vs->sasl.conn, SASL_SEC_PROPS, &secprops); if (err != SASL_OK) { VNC_DEBUG("cannot set SASL security props %d (%s)\n", err, sasl_errstring(err, NULL, NULL)); sasl_dispose(&vs->sasl.conn); vs->sasl.conn = NULL; goto authabort; } err = sasl_listmech(vs->sasl.conn, NULL, /* Don't need to set user */ "", /* Prefix */ ",", /* Separator */ "", /* Suffix */ &mechlist, NULL, NULL); if (err != SASL_OK) { VNC_DEBUG("cannot list SASL mechanisms %d (%s)\n", err, sasl_errdetail(vs->sasl.conn)); sasl_dispose(&vs->sasl.conn); vs->sasl.conn = NULL; goto authabort; } VNC_DEBUG("Available mechanisms for client: '%s'\n", mechlist); vs->sasl.mechlist = g_strdup(mechlist); mechlistlen = strlen(mechlist); vnc_write_u32(vs, mechlistlen); vnc_write(vs, mechlist, mechlistlen); vnc_flush(vs); VNC_DEBUG("Wait for client mechname length\n"); vnc_read_when(vs, protocol_client_auth_sasl_mechname_len, 4); return; authabort: vnc_client_error(vs); }