You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Simon Fuhrer (privat)" <si...@tecbiz.ch> on 2007/08/04 18:17:15 UTC

mod_auth_sspi

hello

I extend the module mod_auth_sspi to provide some password features 
(password revoked, Password must change ...). All works fine but i think 
that the modul has a bug and i don't know how to resolv it. i'm not the 
absolute programmer but small things are ok for me. :-) I think you can 
help me. 

The Module provide a negotiate method and a normal Basic auth. Within 
the basic auth the Auth-name that was specified in the configuration 
will not be displayed on the basic auth box on Windows Firefox or 
Internet Explorer. When the Module receive a Http Header with Basic Auth 
data in it  but not correct Username or Password the basic Auth Pop-op 
and the Authname will displayed. I check the code but all things ok.  
Can you help me?

Sorry for my english.

I hope you understand me.

Cheers Simon

static int check_cleartext_auth(sspi_auth_ctx* ctx)
{
    int ret;
    int i_exp_err;
    DWORD cbOut, cbIn, maxTokenSize;
    BYTE *clientbuf, *serverbuf;
    SECURITY_STATUS ss;
 
    maxTokenSize = get_package_max_token_size(sspiModuleInfo.pkgInfo, 
sspiModuleInfo.numPackages, ctx->scr->package);
    serverbuf = apr_palloc(ctx->r->pool, maxTokenSize);
    clientbuf = NULL;
    cbOut = 0;

    do {
        cbIn = cbOut;
        cbOut = maxTokenSize;
       
        ss = gen_client_context(sspiModuleInfo.functable, 
&ctx->scr->client_credentials, &ctx->scr->client_context,
                                &ctx->scr->client_ctxtexpiry, clientbuf, 
&cbIn, serverbuf, &cbOut,
                                ctx->scr->package);

        if (ss == SEC_E_OK || ss == SEC_I_CONTINUE_NEEDED || ss == 
SEC_I_COMPLETE_AND_CONTINUE) {
            if (clientbuf == NULL) {
                clientbuf = apr_palloc(ctx->r->pool, maxTokenSize);
            }

            cbIn = cbOut;
            cbOut = maxTokenSize;
           
            ss = gen_server_context(sspiModuleInfo.functable, 
&ctx->scr->server_credentials, &ctx->scr->server_context,
                                    &ctx->scr->server_ctxtexpiry, 
serverbuf, &cbIn, clientbuf, &cbOut);
        }
    } while (ss == SEC_I_CONTINUE_NEEDED || ss == 
SEC_I_COMPLETE_AND_CONTINUE);

    switch (ss) {
        case SEC_E_OK:
            return OK;

        case SEC_E_INVALID_HANDLE:
        case SEC_E_INTERNAL_ERROR:
        case SEC_E_NO_AUTHENTICATING_AUTHORITY:
        case SEC_E_INSUFFICIENT_MEMORY:
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 
APR_FROM_OS_ERROR(GetLastError()), ctx->r,
                "access to %s failed, reason: cannot generate context", 
ctx->r->uri);
            return HTTP_INTERNAL_SERVER_ERROR;

        case SEC_E_INVALID_TOKEN:
        case SEC_E_LOGON_DENIED:

        default:
           
            i_exp_err = GetLastError();
            log_sspi_logon_denied(ctx->r, &ctx->hdr, 
APR_FROM_OS_ERROR(GetLastError()));
       
            if (SSPI_PWDEXPIRED)
            {
                ret = ctx->crec->sspi_pwdexpired_httpcode;
               
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 
APR_FROM_OS_ERROR(GetLastError()), ctx->r,
                "access to %s failed, reason: pw must change", ctx->r->uri);
                return ret;
            }
            else
            {   
                ret = HTTP_UNAUTHORIZED;
                note_sspi_auth_failure(ctx->r);
                cleanup_sspi_connection(ctx->scr);
                return ret;
            }
           
           
    }




int get_sspi_header(sspi_auth_ctx* ctx)
{
    char* scheme;
    char* basicline = 0;
    //const char *auth_hdr = get_authenticate_header_name(r);
    const char *auth_line = apr_table_get(ctx->r->headers_in,
        get_authorization_header_name(ctx->r));



    /*
     * If the client didn't supply an Authorization: (or 
Proxy-Authorization)
     * header, we need to reply 401 and supply a WWW-Authenticate
     * (or Proxy-Authenticate) header indicating acceptable authentication
     * schemes.
     */
    if (!auth_line) {
   
        note_sspi_auth_failure(ctx->r);
       
        return HTTP_UNAUTHORIZED;
    }


    /*
     * Do a quick check of the Authorization: header. If it is 'Basic', 
and we're
     * allowed, try a cleartext logon. Else if it isn't the selected 
package
     * and we're authoritative, reply 401 again.
     */
    scheme = ap_getword_white(ctx->r->pool, &auth_line);

    if (ctx->crec->sspi_offersspi && 0 == check_package_valid(ctx, 
scheme)) {
      if (0 == ctx->scr->package)
        ctx->scr->package = apr_pstrdup(ctx->r->connection->pool, scheme);
      return get_sspi_userpass(ctx, auth_line);
    } else if (ctx->crec->sspi_offerbasic && 0 == lstrcmpi(scheme, 
"Basic")) {
      ctx->scr->package = ctx->crec->sspi_package_basic;
      return get_basic_userpass(ctx, auth_line);
    }

    if (ctx->crec->sspi_authoritative) {
        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ctx->r,
            "client used wrong authentication scheme: %s for %s (needed 
%s)",
            ctx->scr->package, ctx->r->uri, ctx->crec->sspi_packages);
        note_sspi_auth_failure(ctx->r);
        return HTTP_UNAUTHORIZED;
    } else {
        return DECLINED;
    }



    return HTTP_INTERNAL_SERVER_ERROR;
}

void note_sspi_auth_failure(request_rec *r)
{
  const char *auth_hdr = get_authenticate_header_name(r);
  sspi_config_rec *crec = get_sspi_config_rec(r);

  char* basicline = 0;

  apr_table_unset(r->err_headers_out, auth_hdr);
               

  if (crec->sspi_offerbasic)
    {
                          
    basicline = apr_psprintf(r->pool, "Basic realm=TESTSTSTSTST"); //, 
//ap_auth_name(r));
    }

  if (crec->sspi_offersspi)
    {
    sspi_connection_rec* scr = 0;
    apr_pool_userdata_get(&scr, sspiModuleInfo.userDataKeyString, 
r->connection->pool);
   
    if (scr == 0 || scr->sspi_failing == 0)
      {
      char* w;
      const char* package_list = crec->sspi_packages;

      if (crec->sspi_offerbasic && crec->sspi_basicpreferred)
        {
        apr_table_addn(r->err_headers_out, auth_hdr, basicline);
        basicline = 0;
        }

      if (package_list) while (*package_list)
        {
        w = ap_getword_white(r->pool, &package_list);
        if (w[0])
          {
          apr_table_addn(r->err_headers_out, auth_hdr, w);
          }
        }
      }
    }

  apr_table_addn(r->err_headers_out, auth_hdr, basicline);
  if (basicline != 0)
    {

                    
    apr_table_addn(r->err_headers_out, auth_hdr, basicline);
    }
}