Beispiel #1
0
static int
kvno5(krb5_context ctx, const char *host, int socktype, krb5_principal princ,
    krb5_principal sprinc, krb5_ccache ccache)
{
	krb5_error_code	 kerr = 0;
	krb5_creds	 increds;
	krb5_creds	*outcreds = NULL;
	krb5_ticket	*ticket = NULL;

	VERBOSE(1, (stderr, "initiating kvno5/%s ping to %s\n",
	    socktype == SOCK_DGRAM ? "udp" : "tcp", host));

	memset(&increds, 0x0, sizeof(increds));
	increds.client = princ;
	increds.server = sprinc;
	kerr = krb5_get_credentials(ctx, 0, ccache, &increds, &outcreds);
	if (kerr)
		goto bail;

        kerr = krb5_decode_ticket(&outcreds->ticket, &ticket);
        if (kerr)
		goto bail;

	VERBOSE(2, (stderr, "kvno5 says kvno = %d\n", ticket->enc_part.kvno));

bail:
	if (kerr)
		fail_msg("kvno5", socktype, host, error_message(kerr));
	if (ticket)
		krb5_free_ticket(ctx, ticket);
	if (outcreds)
		krb5_free_creds(ctx, outcreds);

	return kerr;
}
Beispiel #2
0
static void
copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
    krb5_error_code code;
    krb5_ticket *ticket;
    size_t len;

    code = krb5_decode_ticket(&v5cred->ticket, &ticket);
    if (code == 0) {
        len = krb5_princ_realm(context, ticket->server)->length;
        if (len > destlen - 1)
            len = destlen - 1;

        strncpy(dest, krb5_princ_realm(context, ticket->server)->data, len);
        dest[len] = '\0';

        krb5_free_ticket(context, ticket);
    }
}
Beispiel #3
0
int print_ccache (kim_ccache in_ccache, int *out_found_valid_tgt)
{
    kim_error err = 0;
    kim_credential_iterator iterator = NULL;
    kim_identity ccache_identity = NULL;
    kim_string type = NULL;
    kim_string name = NULL;
    kim_string ccache_identity_string = NULL;
    int found_tickets = 0;

    *out_found_valid_tgt = 0;
    
    if (!err) {
        err = kim_ccache_get_type (in_ccache, &type);
        printiferr (err, "while getting the ccache type");
    }
    
    if (!err) {
        err = kim_ccache_get_name (in_ccache, &name);
        printiferr (err, "while getting the ccache name");
    }
    
    if (!err) {
        err = kim_ccache_get_client_identity (in_ccache, &ccache_identity);
        printiferr (err, "while getting the ccache principal");
   }
    
    if (!err) {
        err = kim_identity_get_display_string (ccache_identity, 
                                               &ccache_identity_string);
        printiferr (err, "while unparsing the ccache principal name");
    }
    
    if (!err) {
        printmsg ("Kerberos 5 ticket cache: '%s:%s'\nDefault principal: %s\n\n",
                  type, name, ccache_identity_string);
        printmsg ("Valid Starting");
        printfiller (' ', get_timestamp_width () - sizeof ("Valid Starting") + 3);
        printmsg ("Expires");
        printfiller (' ', get_timestamp_width () - sizeof ("Expires") + 3);
        printmsg ("Service Principal\n");
        
        err = kim_credential_iterator_create (&iterator, in_ccache);
    }
    
    while (!err) {
        kim_credential credential = NULL;
        kim_identity client = NULL;
        kim_identity service = NULL;
        kim_string client_string = NULL;
        kim_string service_string = NULL;
        krb5_creds *creds = NULL;
        int extra_field = 0;
        
        err = kim_credential_iterator_next (iterator, &credential);
        if (!err && !credential) { break; }
        
        if (!err) {
            err = kim_credential_get_client_identity (credential, &client);
            printiferr (err, "while getting the client principal");
        }

        if (!err) {
            err = kim_identity_get_display_string (client, &client_string);
            printiferr (err, "while unparsing the client principal name");
        }
        
        if (!err) {
            err = kim_credential_get_service_identity (credential, &service);
            printiferr (err, "while getting the service principal");
        }
        
        if (!err) {
            err = kim_identity_get_display_string (service, &service_string);
            printiferr (err, "while unparsing the service principal name");
        }
        
        if (!err) {
            err = kim_credential_get_krb5_creds (credential, kcontext, &creds);
            printiferr (err, "while getting krb5 creds");
        }
                
	if (!err && krb5_is_config_principal(kcontext, creds->server))
	    goto next;

        if (!err) {
            found_tickets = 1;
            
            printtime (creds->times.starttime ? creds->times.starttime : creds->times.authtime);
            printmsg ("  ");
            printtime (creds->times.endtime);
            printmsg ("  ");
            printmsg ("%s\n", service_string);
            
            if (strcmp (ccache_identity_string, client_string)) {
                if (!extra_field) {
                    printmsg ("\t");
                }
                printmsg ("for client %s", client_string);
                extra_field++;
            }
            
            if (creds->ticket_flags & TKT_FLG_RENEWABLE) {
                printmsg (extra_field ? ", " : "\t");
                printmsg ("renew until ");
                printtime (creds->times.renew_till);
                extra_field += 2;
            }
            
            if (extra_field > 2) {
                printmsg ("\n");
                extra_field = 0;
            }
            
            if (show_flags) {
                printmsg (extra_field ? ", " : "\t");
                printflags (creds->ticket_flags);
                extra_field++;
            }
            
            if (extra_field > 2) {
                printmsg ("\n");
                extra_field = 0;
            }
            
            if (show_enctypes) {
                krb5_ticket *ticket_rep;
                
                if (krb5_decode_ticket (&creds->ticket, &ticket_rep) == 0) {
                    if (!extra_field) {
                        printmsg ("\t");
                    } else {
                        printmsg (", ");
                    }
                    printmsg ("Etype (skey, tkt): %s, ", 
                              enctype_to_string (creds->keyblock.enctype));
                    printmsg ("%s ", 
                              enctype_to_string (ticket_rep->enc_part.enctype));
                    extra_field++;
                    
                    krb5_free_ticket (kcontext, ticket_rep);
                }
            }
            
            if (extra_field) {
                printmsg ("\n");
            }
            
            if (show_address_list) {
                printmsg ("\tAddresses: ");
                if (!creds->addresses || !creds->addresses[0]) {
                    printmsg ("(none)\n");
                } else {
                    int i;
                    
                    for (i = 0; creds->addresses[i]; i++) {
                        if (i > 0) {
                            printmsg (", ");
                        }
                        printaddress (*creds->addresses[i]);
                    }
                    printmsg ("\n");
                }
            }
            if (extra_field) {
                printmsg ("\n");
            }
            
        }
        
        if (!err) {
            kim_boolean is_tgt = 0;
            kim_credential_state state;
            
            err = kim_credential_is_tgt (credential, &is_tgt);
            printiferr (err, "while checking if creds are valid");
           
            if (!err) {
                err = kim_credential_get_state (credential, &state);
            }
            
            if (!err && is_tgt && state == kim_credentials_state_valid) { 
                *out_found_valid_tgt = 1;
            }
        }
        
    next:
        if (creds) { krb5_free_creds (kcontext, creds); }
        kim_string_free (&client_string);
        kim_string_free (&service_string);
        kim_identity_free (&client);
        kim_identity_free (&service);
        kim_credential_free (&credential);
    }
        
    kim_string_free (&type);
    kim_string_free (&name);
    kim_string_free (&ccache_identity_string);
    kim_identity_free (&ccache_identity);
    kim_credential_iterator_free (&iterator);
    
    if (!err) {
        if (!found_tickets) {
            printerr ("No Kerberos 5 tickets in credentials cache\n");
        } else {
            printmsg ("\n");
        }
    }

    return err;
}
/*
 * call-seq:
 *   list_cache([cache_name]) -> array
 *
 * Call krb5_cc_next_cred to fetch credentials from a cachefile.  With no parameters, it fetches the credentials in the default cachefile.  With one parameter, it fetches the credentials in the named cachefile.  Returns a list of Krb5Auth::Krb5::Cred objects on success, raises Krb5Auth::Krb5::Exception on failure.
 */
static VALUE Krb5_list_cache_creds(int argc, VALUE *argv, VALUE self)
{
  VALUE cache_val;
  struct ruby_krb5 *kerb;
  krb5_error_code krbret;
  char *cache_name;
  krb5_ccache cc;
  krb5_cc_cursor cur;
  krb5_creds creds;
  char *name;
  char *sname;
  krb5_ticket *tkt;
  VALUE result;
  VALUE line;

  rb_scan_args(argc, argv, "01", &cache_val);

  cache_name = get_string_or_nil(cache_val);

  Data_Get_Struct(self, struct ruby_krb5, kerb);
  if (!kerb) {
    NOSTRUCT_EXCEPT();
    return Qfalse;
  }

  if (cache_name == NULL) {
    krbret = krb5_cc_default(kerb->ctx, &cc);
  }
  else {
    krbret = krb5_cc_resolve(kerb->ctx, cache_name, &cc);
  }

  if (krbret) {
    goto cache_fail_raise;
  }

  krbret = krb5_cc_start_seq_get(kerb->ctx, cc, &cur);
  if (krbret) {
    goto cache_fail_close;
  }

  result = rb_ary_new();
  while (!(krbret = krb5_cc_next_cred(kerb->ctx, cc, &cur, &creds))) {
    krbret = krb5_unparse_name(kerb->ctx, creds.client, &name);
    if (krbret) {
      krb5_free_cred_contents(kerb->ctx, &creds);
      break;
    }
    krbret = krb5_unparse_name(kerb->ctx, creds.server, &sname);
    if (krbret) {
      free(name);
      krb5_free_cred_contents(kerb->ctx, &creds);
      break;
    }
    krbret = krb5_decode_ticket(&creds.ticket, &tkt);
    if (krbret) {
      free(sname);
      free(name);
      krb5_free_cred_contents(kerb->ctx, &creds);
      break;
    }
    line = rb_class_new_instance(0, NULL, cCred);
    rb_iv_set(line, "@client", rb_str_new2(name));
    rb_iv_set(line, "@server", rb_str_new2(sname));
    rb_iv_set(line, "@starttime", INT2NUM(creds.times.starttime));
    rb_iv_set(line, "@authtime", INT2NUM(creds.times.authtime));
    rb_iv_set(line, "@endtime", INT2NUM(creds.times.endtime));
    rb_iv_set(line, "@ticket_flags", INT2NUM(creds.ticket_flags));
    rb_iv_set(line, "@cred_enctype", INT2NUM(creds.keyblock.enctype));
    rb_iv_set(line, "@ticket_enctype", INT2NUM(tkt->enc_part.enctype));
    rb_ary_push(result, line);
    krb5_free_ticket(kerb->ctx, tkt);
    free(sname);
    free(name);
    krb5_free_cred_contents(kerb->ctx, &creds);
  }

  if (krbret != KRB5_CC_END) {
    // FIXME: do we need to free up "result" here?  There will be no
    // references to it, so I think the garbage collector will pick it up,
    // but I'm not sure.

    goto cache_fail_close;
  }

  krbret = krb5_cc_end_seq_get(kerb->ctx, cc, &cur);

  krb5_cc_close(kerb->ctx, cc);

  return result;

 cache_fail_close:
  krb5_cc_close(kerb->ctx, cc);

 cache_fail_raise:
  Krb5_register_error(krbret);

  return Qfalse;
}
Beispiel #5
0
krb5_error_code sss_extract_pac(krb5_context ctx,
                                krb5_ccache ccache,
                                krb5_principal server_principal,
                                krb5_principal client_principal,
                                krb5_keytab keytab,
                                krb5_authdata ***_pac_authdata)
{
#ifdef HAVE_PAC_RESPONDER
    krb5_error_code kerr;
    krb5_creds mcred;
    krb5_creds cred;
    krb5_authdata **pac_authdata = NULL;
    krb5_pac pac = NULL;
    int ret;
    krb5_ticket *ticket = NULL;
    krb5_keytab_entry entry;

    memset(&entry, 0, sizeof(entry));
    memset(&mcred, 0, sizeof(mcred));
    memset(&cred, 0, sizeof(mcred));

    mcred.server = server_principal;
    mcred.client = client_principal;

    kerr = krb5_cc_retrieve_cred(ctx, ccache, 0, &mcred, &cred);
    if (kerr != 0) {
        DEBUG(SSSDBG_OP_FAILURE, "krb5_cc_retrieve_cred failed.\n");
        goto done;
    }

    kerr = krb5_decode_ticket(&cred.ticket, &ticket);
    if (kerr != 0) {
        DEBUG(SSSDBG_OP_FAILURE, "krb5_decode_ticket failed.\n");
        goto done;
    }

    kerr = krb5_server_decrypt_ticket_keytab(ctx, keytab, ticket);
    if (kerr != 0) {
        DEBUG(SSSDBG_OP_FAILURE, "krb5_server_decrypt_ticket_keytab failed.\n");
        goto done;
    }

    kerr = sss_krb5_find_authdata(ctx,
                                  ticket->enc_part2->authorization_data, NULL,
                                  KRB5_AUTHDATA_WIN2K_PAC, &pac_authdata);
    if (kerr != 0) {
        DEBUG(SSSDBG_OP_FAILURE, "krb5_find_authdata failed.\n");
        goto done;
    }

    if (pac_authdata == NULL || pac_authdata[0] == NULL) {
        DEBUG(SSSDBG_OP_FAILURE, "No PAC authdata available.\n");
        kerr = ENOENT;
        goto done;
    }

    if (pac_authdata[1] != NULL) {
        DEBUG(SSSDBG_OP_FAILURE, "More than one PAC autdata found.\n");
        kerr = EINVAL;
        goto done;
    }

    kerr = krb5_pac_parse(ctx, pac_authdata[0]->contents,
                          pac_authdata[0]->length, &pac);
    if (kerr != 0) {
        DEBUG(SSSDBG_OP_FAILURE, "krb5_pac_parse failed.\n");
        goto done;
    }

    kerr = krb5_kt_get_entry(ctx, keytab, ticket->server,
                             ticket->enc_part.kvno, ticket->enc_part.enctype,
                             &entry);
    if (kerr != 0) {
        DEBUG(SSSDBG_OP_FAILURE, "krb5_kt_get_entry failed.\n");
        goto done;
    }

    kerr = krb5_pac_verify(ctx, pac, 0, NULL, &entry.key, NULL);
    if (kerr != 0) {
        DEBUG(SSSDBG_OP_FAILURE, "krb5_pac_verify failed.\n");
        goto done;
    }

    ret = unsetenv("_SSS_LOOPS");
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to unset _SSS_LOOPS, "
                  "sss_pac_make_request will most certainly fail.\n");
    }

    *_pac_authdata = pac_authdata;
    kerr = 0;

done:
    if (kerr != 0) {
        krb5_free_authdata(ctx, pac_authdata);
    }
    if (entry.magic != 0) {
        krb5_free_keytab_entry_contents(ctx, &entry);
    }
    krb5_pac_free(ctx, pac);
    if (ticket != NULL) {
        krb5_free_ticket(ctx, ticket);
    }

    krb5_free_cred_contents(ctx, &cred);
    return kerr;
#else
    return ENOTSUP;
#endif
}
Beispiel #6
0
DWORD
LwKrb5InitializeUserLoginCredentials(
    IN PCSTR pszUserPrincipalName,
    IN PCSTR pszPassword,
    IN uid_t uid,
    IN gid_t gid,
    IN LW_KRB5_LOGIN_FLAGS Flags,
    IN PCSTR pszServicePrincipal,
    IN PCSTR pszServiceRealm,
    IN PCSTR pszServicePassword,
    OUT PVOID* ppNdrPacInfo,
    OUT size_t* pNdrPacInfoSize,
    OUT PDWORD pdwGoodUntilTime
    )
{
    DWORD dwError = 0;
    krb5_error_code ret = 0;
    krb5_context ctx = NULL;
    krb5_ccache cc = NULL;
    // Free with krb5_free_cred_contents
    krb5_creds credsRequest = {0};
    krb5_creds *pTgsCreds = NULL;
    krb5_ticket *pTgsTicket = NULL;
    krb5_ticket *pDecryptedTgs = NULL;
    krb5_auth_context authContext = NULL;
    krb5_data apReqPacket = {0};
    krb5_keyblock serviceKey = {0};
    krb5_data salt = {0};
    // Do not free
    krb5_data machinePassword = {0};
    krb5_flags flags = 0;
    krb5_int32 authcon_flags = 0;
    BOOLEAN bInLock = FALSE;
    PCSTR pszTempCacheName = NULL;
    PSTR pszTempCachePath = NULL;
    PVOID pNdrPacInfo = NULL;
    size_t ndrPacInfoSize = 0;
    DWORD dwGoodUntilTime = 0;

    ret = krb5_init_context(&ctx);
    BAIL_ON_KRB_ERROR(ctx, ret);

    /* Generates a new filed based credentials cache in /tmp. The file will
     * be owned by root and only accessible by root.
     */
    ret = krb5_cc_new_unique(
            ctx, 
            "FILE",
            "hint",
            &cc);
    BAIL_ON_KRB_ERROR(ctx, ret);


    if (Flags & LW_KRB5_LOGIN_FLAG_SMART_CARD)
    {
        dwError = LwKrb5GetTgtWithSmartCard(
                pszUserPrincipalName,
                pszPassword,
                krb5_cc_get_name(ctx, cc),
                &dwGoodUntilTime);
    }
    else
    {
        dwError = LwKrb5GetTgt(
                pszUserPrincipalName,
                pszPassword,
                krb5_cc_get_name(ctx, cc),
                &dwGoodUntilTime);
    }

    BAIL_ON_LW_ERROR(dwError);

    ret = krb5_parse_name(ctx, pszServicePrincipal, &credsRequest.server);
    BAIL_ON_KRB_ERROR(ctx, ret);

    ret = krb5_cc_get_principal(ctx, cc, &credsRequest.client);
    BAIL_ON_KRB_ERROR(ctx, ret);
 
    /* Get a TGS for our service using the tgt in the cache */
    ret = krb5_get_credentials(
            ctx,
            0, /*no options (not user to user encryption,
                 and not only cached) */
            cc,
            &credsRequest,
            &pTgsCreds);

    // Don't trust pTgsCreds on an unsuccessful return
    // This may be non-zero due to the krb5 libs following referrals
    // but has been freed in the krb5 libs themselves and any useful
    // tickets have already been cached.
    if (ret != 0) {
        pTgsCreds = NULL;
    }
    
    BAIL_ON_KRB_ERROR(ctx, ret);

    //No need to store the tgs in the cc. Kerberos does that automatically

    /* Generate an ap_req message, but don't send it anywhere. Just decode it
     * immediately. This is the only way to get kerberos to decrypt the tgs
     * using public APIs */
    ret = krb5_mk_req_extended(
            ctx,
            &authContext,
            0, /* no options necessary */
            NULL, /* since this isn't a real ap_req, we don't have any
                     supplemental data to send with it. */
            pTgsCreds,
            &apReqPacket);
    BAIL_ON_KRB_ERROR(ctx, ret);

    /* Decode (but not decrypt) the tgs ticket so that we can figure out
     * which encryption type was used in it. */
    ret = krb5_decode_ticket(&pTgsCreds->ticket, &pTgsTicket);

    /* The TGS ticket is encrypted with the machine password and salted with
     * the service principal. pszServicePrincipal could probably be used
     * directly, but it's safer to unparse pTgsCreds->server, because the KDC
     * sent that to us.
     */
    salt.magic = KV5M_DATA;
    ret = krb5_unparse_name(
            ctx,
            pTgsCreds->server,
            &salt.data);
    BAIL_ON_KRB_ERROR(ctx, ret);
    salt.length = strlen(salt.data);

    machinePassword.magic = KV5M_DATA;
    machinePassword.data = (PSTR)pszServicePassword,
    machinePassword.length = strlen(pszServicePassword),

    /* Generate a key to decrypt the TGS */
    ret = krb5_c_string_to_key(
            ctx,
            pTgsTicket->enc_part.enctype,
            &machinePassword,
            &salt,
            &serviceKey);
    BAIL_ON_KRB_ERROR(ctx, ret);

    /* Typically krb5_rd_req would decode the AP_REQ using the keytab, but
     * we don't want to depend on the keytab. As a side effect of kerberos'
     * user to user authentication support, if a key is explictly set on the
     * auth context, that key will be used to decrypt the TGS instead of the
     * keytab.
     *
     * By manually generating the key and setting it, we don't require
     * a keytab.
     */
    if (authContext != NULL)
    {
        ret = krb5_auth_con_free(ctx, authContext);
        BAIL_ON_KRB_ERROR(ctx, ret);
    }
    
    ret = krb5_auth_con_init(ctx, &authContext);
    BAIL_ON_KRB_ERROR(ctx, ret);

    ret = krb5_auth_con_setuseruserkey(
            ctx,
            authContext,
            &serviceKey);
    BAIL_ON_KRB_ERROR(ctx, ret);

    /* Disable replay detection which is unnecessary and
     * can fail when authenticating large numbers of users.
     */
    krb5_auth_con_getflags(ctx,
                           authContext,
                           &authcon_flags);
    krb5_auth_con_setflags(ctx,
                           authContext,
                           authcon_flags & ~KRB5_AUTH_CONTEXT_DO_TIME);


    if (pszServiceRealm)
    {
        ret = krb5_set_default_realm(ctx, pszServiceRealm);
        BAIL_ON_KRB_ERROR(ctx, ret);
    }

    /* This decrypts the TGS. As a side effect it ensures that the KDC that
     * the user's TGT came from is in the same realm that the machine was
     * joined to (this prevents users from spoofing the KDC).
     */
    ret = krb5_rd_req(
            ctx,
            &authContext,
            &apReqPacket,
            pTgsCreds->server,
            NULL, /* we're not using the keytab */
            &flags,
            &pDecryptedTgs);
    BAIL_ON_KRB_ERROR(ctx, ret);

    dwError = LwKrb5FindPac(
        ctx,
        pDecryptedTgs,
        &serviceKey,
        &pNdrPacInfo,
        &ndrPacInfoSize);
    BAIL_ON_LW_ERROR(dwError);

    if (Flags & LW_KRB5_LOGIN_FLAG_UPDATE_CACHE)
    {
        /* 1. Copy old credentials from the existing user creds cache to
         *      the temporary cache.
         * 2. Delete the existing creds cache.
         * 3. Move the temporary cache file into the final path.
         */
        dwError = pthread_mutex_lock(&gLwKrb5State.UserCacheMutex);
        BAIL_ON_LW_ERROR(dwError);
        bInLock = TRUE;

        dwError = LwKrb5CopyFromUserCache(
                    ctx,
                    cc,
                    uid
                    );
        BAIL_ON_LW_ERROR(dwError);

        pszTempCacheName = krb5_cc_get_name(ctx, cc);
        if (!strncasecmp(pszTempCacheName, "FILE:", sizeof("FILE:")-1)) {
            pszTempCacheName += sizeof("FILE:") - 1;
        }

        dwError = LwAllocateString(pszTempCacheName, &pszTempCachePath);
        BAIL_ON_LW_ERROR(dwError);

        krb5_cc_close(ctx, cc);
        // Just to make sure no one accesses this now invalid pointer
        cc = NULL;

        dwError = LwKrb5MoveCCacheToUserPath(
                    ctx,
                    pszTempCachePath,
                    uid,
                    gid);
        if (dwError != LW_ERROR_SUCCESS)
        {
            /* Let the user login, even if we couldn't create the ccache for
             * them. Possible causes are:
             * 1. /tmp is readonly
             * 2. Another user maliciously setup a weird file (such as a
             *    directory) where the ccache would go.
             * 3. Someone created a ccache in the small window after we delete
             *    the old one and before we move in the new one.
             */
            LW_LOG_WARNING("Unable to set up credentials cache with tgt for uid %ld", (long)uid);
            dwError = LwRemoveFile(pszTempCachePath);
            BAIL_ON_LW_ERROR(dwError);
        }
    }

error:
    if (dwError)
    {
        LW_SAFE_FREE_MEMORY(pNdrPacInfo);
        ndrPacInfoSize = 0;
        dwGoodUntilTime = 0;
    }

    if (ctx)
    {
        // This function skips fields which are NULL
        krb5_free_cred_contents(ctx, &credsRequest);
    
        if (pTgsCreds != NULL)
        {
            krb5_free_creds(ctx, pTgsCreds);
        }
        
        if (pTgsTicket != NULL)
        {
            krb5_free_ticket(ctx, pTgsTicket);
        }
        
        if (pDecryptedTgs != NULL)
        {
            krb5_free_ticket(ctx, pDecryptedTgs);
        }
        
        if (authContext != NULL)
        {
            krb5_auth_con_free(ctx, authContext);
        }
        
        krb5_free_data_contents(ctx, &apReqPacket);
        krb5_free_data_contents(ctx, &salt);
        krb5_free_keyblock_contents(ctx, &serviceKey);

        if (cc != NULL)
        {
            krb5_cc_destroy(ctx, cc);
        }
        krb5_free_context(ctx);
    }
    if (bInLock)
    {
        pthread_mutex_unlock(&gLwKrb5State.UserCacheMutex);
    }
    LW_SAFE_FREE_STRING(pszTempCachePath);

    *ppNdrPacInfo = pNdrPacInfo;
    *pNdrPacInfoSize = ndrPacInfoSize;
    *pdwGoodUntilTime = dwGoodUntilTime;

    return dwError;
}
Beispiel #7
0
static void
show_credential(krb5_creds *cred)
{
    krb5_error_code ret;
    krb5_ticket *tkt;
    char *name, *sname, *flags;
    int extra_field = 0, ccol = 0, i;

    ret = krb5_unparse_name(context, cred->client, &name);
    if (ret) {
        com_err(progname, ret, _("while unparsing client name"));
        return;
    }
    ret = krb5_unparse_name(context, cred->server, &sname);
    if (ret) {
        com_err(progname, ret, _("while unparsing server name"));
        krb5_free_unparsed_name(context, name);
        return;
    }
    if (!cred->times.starttime)
        cred->times.starttime = cred->times.authtime;

    if (!krb5_is_config_principal(context, cred->server)) {
        printtime(cred->times.starttime);
        putchar(' ');
        putchar(' ');
        printtime(cred->times.endtime);
        putchar(' ');
        putchar(' ');
        printf("%s\n", sname);
    } else {
        fputs("config: ", stdout);
        ccol = 8;
        for (i = 1; i < cred->server->length; i++) {
            ccol += printf("%s%.*s%s",
                           i > 1 ? "(" : "",
                           (int)cred->server->data[i].length,
                           cred->server->data[i].data,
                           i > 1 ? ")" : "");
        }
        fputs(" = ", stdout);
        ccol += 3;
    }

    if (strcmp(name, defname)) {
        printf(_("\tfor client %s"), name);
        extra_field++;
    }

    if (krb5_is_config_principal(context, cred->server))
        print_config_data(ccol, &cred->ticket);

    if (cred->times.renew_till) {
        if (!extra_field)
            fputs("\t",stdout);
        else
            fputs(", ",stdout);
        fputs(_("renew until "), stdout);
        printtime(cred->times.renew_till);
        extra_field += 2;
    }

    if (extra_field > 3) {
        fputs("\n", stdout);
        extra_field = 0;
    }

    if (show_flags) {
        flags = flags_string(cred);
        if (flags && *flags) {
            if (!extra_field)
                fputs("\t",stdout);
            else
                fputs(", ",stdout);
            printf(_("Flags: %s"), flags);
            extra_field++;
        }
    }

    if (extra_field > 2) {
        fputs("\n", stdout);
        extra_field = 0;
    }

    if (show_etype) {
        ret = krb5_decode_ticket(&cred->ticket, &tkt);
        if (ret)
            goto err_tkt;

        if (!extra_field)
            fputs("\t",stdout);
        else
            fputs(", ",stdout);
        printf(_("Etype (skey, tkt): %s, "),
               etype_string(cred->keyblock.enctype));
        printf("%s ", etype_string(tkt->enc_part.enctype));
        extra_field++;

    err_tkt:
        if (tkt != NULL)
            krb5_free_ticket(context, tkt);
    }

    if (show_adtype) {
        if (cred->authdata != NULL) {
            if (!extra_field)
                fputs("\t",stdout);
            else
                fputs(", ",stdout);
            printf(_("AD types: "));
            for (i = 0; cred->authdata[i] != NULL; i++) {
                if (i)
                    printf(", ");
                printf("%d", cred->authdata[i]->ad_type);
            }
            extra_field++;
        }
    }

    /* If any additional info was printed, extra_field is non-zero. */
    if (extra_field)
        putchar('\n');

    if (show_addresses) {
        if (cred->addresses == NULL || cred->addresses[0] == NULL) {
            printf(_("\tAddresses: (none)\n"));
        } else {
            printf(_("\tAddresses: "));
            one_addr(cred->addresses[0]);

            for (i = 1; cred->addresses[i] != NULL; i++) {
                printf(", ");
                one_addr(cred->addresses[i]);
            }

            printf("\n");
        }
    }

    krb5_free_unparsed_name(context, name);
    krb5_free_unparsed_name(context, sname);
}
Beispiel #8
0
tkt_test_1()
{
    krb5_data *data;
    krb5_ticket tk_in, *tk_out;
    krb5_keyblock sess_k, serv_k, *nsess;
    krb5_enc_tkt_part tk_in_enc;
    int code;
    krb5_address *addr_list[2];
    krb5_address addr_1;
    static krb5_octet ip_addr_1[4] = { 18, 72, 0, 122 };
    char *out;

    /*
     * fill in some values on the "in" side of the ticket
     */
    code = krb5_parse_name ("server/test/[email protected]", &tk_in.server);
    if (code != 0) {
        com_err("tkt_test_1", code, " parsing server principal");
        return;
    }

    serv_k.enctype = 1;         /* XXX symbolic constant */
    serv_k.length = 8;          /* XXX symbolic constant */
    serv_k.contents = key_one;

    sess_k.enctype = 1;         /* XXX symbolic constant */
    sess_k.length = 8;          /* XXX symbolic constant */
    sess_k.contents = key_two;

    tk_in.etype = 1;            /* XXX symbolic constant here */
    tk_in.skvno = 4;

    tk_in.enc_part2 = &tk_in_enc;

    tk_in_enc.flags = 0x11;
    tk_in_enc.session = &sess_k;

    tk_in_enc.times.authtime = 42;
    tk_in_enc.times.starttime = 43;
    tk_in_enc.times.endtime = 44;

    code = krb5_parse_name ("client/test/[email protected]", &tk_in_enc.client);
    if (code != 0) {
        com_err("tkt_test_1", code, " parsing client principal");
        return;
    }
    tk_in_enc.transited.length = 0;

    addr_1.addrtype = ADDRTYPE_INET; /* XXX should be KRB5_ADDR... */
    addr_1.length = 4;
    addr_1.contents = ip_addr_1;

    addr_list[0] = &addr_1;
    addr_list[1] = 0;


    tk_in_enc.caddrs = addr_list;
    tk_in_enc.authorization_data = 0;

    code = krb5_encrypt_tkt_part(&serv_k, &tk_in);
    if (code != 0) {
        com_err ("tkt_test_1", code, " encrypting ticket");
        return;
    }

    data = 0;

    code = krb5_encode_ticket (&tk_in,  &data);
    if (code != 0) {
        com_err ("tkt_test_1", code, " encoding ticket");
        return;
    }

    dump_data(data);

    tk_out = 0;
    code = krb5_decode_ticket (data, &tk_out);
    if (code != 0) {
        com_err ("tkt_test_1", code, "decoding ticket");
        return;
    }
    /* check the plaintext values */
    if (tk_out->etype != 1) {
        com_err ("tkt_test_1", 0, "wrong etype");
        return;
    }
    if (tk_out->skvno != 4) {
        com_err ("tkt_test_1", 0, "wrong kvno");
        return;
    }

    code = krb5_unparse_name(tk_out->server, &out);
    if (code != 0) {
        com_err ("tkt_test_1", code, "couldn't unparse server principal");
        return;
    }
    if (strcmp (out, "server/test/[email protected]") != 0) {
        com_err("tkt_test_1", 0, "wrong server principal");
        return;
    }
    free(out);
    out = 0;

    /* decode the ciphertext */
    code = krb5_decrypt_tkt_part (&serv_k, tk_out);
    if (code != 0) {
        com_err ("tkt_test_1", code, "while decrypting ticket");
        return;
    }

    /* check the contents */
    if (tk_out->enc_part2->flags != 0x11) {
        com_err("tkt_test_1", 0, "wrong flags");
        return;
    }

    nsess = tk_out->enc_part2->session;

    if (nsess->enctype != 1) {
        com_err("tkt_test_1", 0, "wrong session key type");
        return;
    }
    if (nsess->length != 8) {
        com_err("tkt_test_1", 0, "wrong session key length");
        return;
    }
    if (memcmp(nsess->contents, key_two, 8) != 0) {
        com_err("tkt_test_1", 0, "wrong session key contents");
        return;
    }

    code = krb5_unparse_name(tk_out->enc_part2->client, &out);
    if (code != 0) {
        com_err ("tkt_test_1", code, "couldn't unparse client principal");
        return;
    }
    if (strcmp (out, "client/test/[email protected]") != 0) {
        com_err("tkt_test_1", 0, "wrong client principal");
        return;
    }
    free(out);
    out = 0;
    if (tk_out->enc_part2->transited.length != 0) {
        com_err("tkt_test_1", 0, "wrong transited length");
        return;
    }
    /* XXX should check address here, too */
    /* XXX should check times here */
    /* XXX should check auth. data here */
    printf("test 1 passed\n");
}
Beispiel #9
0
static void do_v5_kvno (int count, char *names[],
                        char * ccachestr, char *etypestr, char *keytab_name,
                        char *sname, int canon, int unknown)
{
    krb5_error_code ret;
    int i, errors;
    krb5_enctype etype;
    krb5_ccache ccache;
    krb5_principal me;
    krb5_creds in_creds, *out_creds;
    krb5_ticket *ticket;
    char *princ;
    krb5_keytab keytab = NULL;

    ret = krb5_init_context(&context);
    if (ret) {
        com_err(prog, ret, "while initializing krb5 library");
        exit(1);
    }

    if (etypestr) {
        ret = krb5_string_to_enctype(etypestr, &etype);
        if (ret) {
            com_err(prog, ret, "while converting etype");
            exit(1);
        }
    } else {
        etype = 0;
    }

    if (ccachestr)
        ret = krb5_cc_resolve(context, ccachestr, &ccache);
    else
        ret = krb5_cc_default(context, &ccache);
    if (ret) {
        com_err(prog, ret, "while opening ccache");
        exit(1);
    }

    if (keytab_name) {
        ret = krb5_kt_resolve(context, keytab_name, &keytab);
        if (ret) {
            com_err(prog, ret, "resolving keytab %s", keytab_name);
            exit(1);
        }
    }

    ret = krb5_cc_get_principal(context, ccache, &me);
    if (ret) {
        com_err(prog, ret, "while getting client principal name");
        exit(1);
    }

    errors = 0;

    for (i = 0; i < count; i++) {
        memset(&in_creds, 0, sizeof(in_creds));

        in_creds.client = me;

        if (sname != NULL) {
            ret = krb5_sname_to_principal(context, names[i],
                                          sname, KRB5_NT_SRV_HST,
                                          &in_creds.server);
        } else {
            ret = krb5_parse_name(context, names[i], &in_creds.server);
        }
        if (ret) {
            if (!quiet)
                com_err(prog, ret, "while parsing principal name %s", names[i]);
            errors++;
            continue;
        }
        if (unknown == 1) {
            krb5_princ_type(context, in_creds.server) = KRB5_NT_UNKNOWN;
        }

        ret = krb5_unparse_name(context, in_creds.server, &princ);
        if (ret) {
            com_err(prog, ret,
                    "while formatting parsed principal name for '%s'",
                    names[i]);
            errors++;
            continue;
        }

        in_creds.keyblock.enctype = etype;

        ret = krb5_get_credentials(context, canon ? KRB5_GC_CANONICALIZE : 0,
                                   ccache, &in_creds, &out_creds);

        krb5_free_principal(context, in_creds.server);

        if (ret) {
            com_err(prog, ret, "while getting credentials for %s", princ);

            krb5_free_unparsed_name(context, princ);

            errors++;
            continue;
        }

        /* we need a native ticket */
        ret = krb5_decode_ticket(&out_creds->ticket, &ticket);
        if (ret) {
            com_err(prog, ret, "while decoding ticket for %s", princ);
            krb5_free_creds(context, out_creds);
            krb5_free_unparsed_name(context, princ);

            errors++;
            continue;
        }

        if (keytab) {
            ret = krb5_server_decrypt_ticket_keytab(context, keytab, ticket);
            if (ret) {
                if (!quiet)
                    printf("%s: kvno = %d, keytab entry invalid", princ, ticket->enc_part.kvno);
                com_err(prog, ret, "while decrypting ticket for %s", princ);
                krb5_free_ticket(context, ticket);
                krb5_free_creds(context, out_creds);
                krb5_free_unparsed_name(context, princ);

                errors++;
                continue;
            }
            if (!quiet)
                printf("%s: kvno = %d, keytab entry valid\n", princ, ticket->enc_part.kvno);
        } else {
            if (!quiet)
                printf("%s: kvno = %d\n", princ, ticket->enc_part.kvno);
        }

        krb5_free_creds(context, out_creds);
        krb5_free_unparsed_name(context, princ);
    }

    if (keytab)
        krb5_kt_close(context, keytab);
    krb5_free_principal(context, me);
    krb5_cc_close(context, ccache);
    krb5_free_context(context);

    if (errors)
        exit(1);

    exit(0);
}