aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Altman <jaltman@secure-endpoints.com>2004-09-10 16:52:59 +0000
committerJeffrey Altman <jaltman@secure-endpoints.com>2004-09-10 16:52:59 +0000
commit2fb649cf381eb2999d298301495a93c5b69c8a0c (patch)
tree46455d9226895207de36d7373809af558e4defb8
parent87128defef4859e36a83146fa5c7f5daaec6d781 (diff)
downloadkrb5-2fb649cf381eb2999d298301495a93c5b69c8a0c.zip
krb5-2fb649cf381eb2999d298301495a93c5b69c8a0c.tar.gz
krb5-2fb649cf381eb2999d298301495a93c5b69c8a0c.tar.bz2
2004-09-10 Jeffrey Altman <jaltman@mit.edu>
* cc_mslsa.c: The following functionality is being committed but commented out because it is not presently available in public Microsoft SDKs - support for KerbSubmitTicket which allows a KERB_CRED message to be forwarded to the LSA. (KERB_SUBMIT_TICKET) - support for the KerbQueryTicketCacheEx2Message which adds the Session Key Enctype to the contents of the response from KerbQueryTicketCacheExMessage. (HAVE_CACHE_INFO_EX2) git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16735 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/lib/krb5/ccache/ChangeLog12
-rw-r--r--src/lib/krb5/ccache/cc_mslsa.c370
2 files changed, 374 insertions, 8 deletions
diff --git a/src/lib/krb5/ccache/ChangeLog b/src/lib/krb5/ccache/ChangeLog
index 09ea4d9..64be621 100644
--- a/src/lib/krb5/ccache/ChangeLog
+++ b/src/lib/krb5/ccache/ChangeLog
@@ -1,3 +1,15 @@
+2004-09-09 Jeffrey Altman <jaltman@mit.edu>
+
+ * cc_mslsa.c: The following functionality is being committed
+ but commented out because it is not presently
+ available in public Microsoft SDKs
+ - support for KerbSubmitTicket which allows a KERB_CRED
+ message to be forwarded to the LSA. (KERB_SUBMIT_TICKET)
+ - support for the KerbQueryTicketCacheEx2Message which
+ adds the Session Key Enctype to the contents of the
+ response from KerbQueryTicketCacheExMessage.
+ (HAVE_CACHE_INFO_EX2)
+
2004-09-01 Jeffrey Altman <jaltman@mit.edu>
* cc_mslsa.c:
diff --git a/src/lib/krb5/ccache/cc_mslsa.c b/src/lib/krb5/ccache/cc_mslsa.c
index 422426a..c782e63 100644
--- a/src/lib/krb5/ccache/cc_mslsa.c
+++ b/src/lib/krb5/ccache/cc_mslsa.c
@@ -1,7 +1,7 @@
/*
* lib/krb5/ccache/cc_mslsa.c
*
- * Copyright 2003 by the Massachusetts Institute of Technology.
+ * Copyright 2003,2004 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -44,7 +44,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * Implementation of read-only microsoft windows lsa credentials cache
+ * Implementation of microsoft windows lsa credentials cache
*/
#ifdef _WIN32
@@ -69,10 +69,11 @@
#define MAX_MSPRINC_SIZE 1024
/* THREAD SAFETY
- * The functions is_windows_2000(), is_windows_xp(), and does_retrieve_ticket_cache_ticket()
- * contain static variables to cache the responses of the tests being performed. There is
- * no harm in the test being performed more than once since the result will always be the
- * same.
+ * The functions is_windows_2000(), is_windows_xp(),
+ * does_retrieve_ticket_cache_ticket() and does_query_ticket_cache_ex2()
+ * contain static variables to cache the responses of the tests being
+ * performed. There is no harm in the test being performed more than
+ * once since the result will always be the same.
*/
static BOOL
@@ -409,6 +410,43 @@ MSCredToMITCred(KERB_EXTERNAL_TICKET *msticket, UNICODE_STRING ClientRealm,
MSTicketToMITTicket(msticket, context, &creds->ticket);
}
+#ifdef HAVE_CACHE_INFO_EX2
+/* CacheInfoEx2ToMITCred is used when we do not need the real ticket */
+static void
+CacheInfoEx2ToMITCred(KERB_TICKET_CACHE_INFO_EX2 *info,
+ krb5_context context, krb5_creds *creds)
+{
+ WCHAR wrealm[128];
+ ZeroMemory(creds, sizeof(krb5_creds));
+ creds->magic=KV5M_CREDS;
+
+ // construct Client Principal
+ wcsncpy(wrealm, info->ClientRealm.Buffer, info->ClientRealm.Length/sizeof(WCHAR));
+ wrealm[info->ClientRealm.Length/sizeof(WCHAR)]=0;
+ UnicodeStringToMITPrinc(&info->ClientName, wrealm, context, &creds->client);
+
+ // construct Service Principal
+ wcsncpy(wrealm, info->ServerRealm.Buffer,
+ info->ServerRealm.Length/sizeof(WCHAR));
+ wrealm[info->ServerRealm.Length/sizeof(WCHAR)]=0;
+ UnicodeStringToMITPrinc(&info->ServerName, wrealm, context, &creds->server);
+
+ creds->keyblock.magic = KV5M_KEYBLOCK;
+ creds->keyblock.enctype = info->SessionKeyType;
+ creds->ticket_flags = info->TicketFlags;
+ MSFlagsToMITFlags(info->TicketFlags, &creds->ticket_flags);
+ creds->times.starttime=FileTimeToUnixTime(&info->StartTime);
+ creds->times.endtime=FileTimeToUnixTime(&info->EndTime);
+ creds->times.renew_till=FileTimeToUnixTime(&info->RenewTime);
+
+ /* MS Tickets are addressless. MIT requires an empty address
+ * not a NULL list of addresses.
+ */
+ creds->addresses = (krb5_address **)malloc(sizeof(krb5_address *));
+ memset(creds->addresses, 0, sizeof(krb5_address *));
+}
+#endif /* HAVE_CACHE_INFO_EX2 */
+
static BOOL
PackageConnectLookup(HANDLE *pLogonHandle, ULONG *pPackageId)
{
@@ -498,6 +536,9 @@ does_retrieve_ticket_cache_ticket (void)
if (FAILED(Status) || FAILED(SubStatus)) {
if ( SubStatus == STATUS_NOT_SUPPORTED )
+ /* The combination of the two CacheOption flags
+ * is not supported; therefore, the new flag is supported
+ */
fCachesTicket = TRUE;
}
fChecked = TRUE;
@@ -506,6 +547,61 @@ does_retrieve_ticket_cache_ticket (void)
return fCachesTicket;
}
+#ifdef HAVE_CACHE_INFO_EX2
+static BOOL
+does_query_ticket_cache_ex2 (void)
+{
+ static BOOL fChecked = FALSE;
+ static BOOL fEx2Response = FALSE;
+
+ if (!fChecked)
+ {
+ NTSTATUS Status = 0;
+ NTSTATUS SubStatus = 0;
+ HANDLE LogonHandle;
+ ULONG PackageId;
+ ULONG RequestSize;
+ PKERB_QUERY_TKT_CACHE_REQUEST pCacheRequest = NULL;
+ PKERB_QUERY_TKT_CACHE_EX2_RESPONSE pCacheResponse = NULL;
+ ULONG ResponseSize;
+
+ RequestSize = sizeof(*pCacheRequest) + 1;
+
+ if (!PackageConnectLookup(&LogonHandle, &PackageId))
+ return FALSE;
+
+ pCacheRequest = (PKERB_QUERY_TKT_CACHE_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize);
+ if (!pCacheRequest) {
+ CloseHandle(LogonHandle);
+ return FALSE;
+ }
+
+ pCacheRequest->MessageType = KerbQueryTicketCacheEx2Message;
+ pCacheRequest->LogonId.LowPart = 0;
+ pCacheRequest->LogonId.HighPart = 0;
+
+ Status = LsaCallAuthenticationPackage( LogonHandle,
+ PackageId,
+ pCacheRequest,
+ RequestSize,
+ &pCacheResponse,
+ &ResponseSize,
+ &SubStatus
+ );
+
+ LocalFree(pCacheRequest);
+ CloseHandle(LogonHandle);
+
+ if (FAILED(Status) || FAILED(SubStatus)) {
+ if ( SubStatus != STATUS_NOT_SUPPORTED )
+ fEx2Response = TRUE;
+ }
+ fChecked = TRUE;
+ }
+
+ return fEx2Response;
+}
+#endif /* HAVE_CACHE_INFO_EX2 */
static DWORD
ConcatenateUnicodeStrings(UNICODE_STRING *pTarget, UNICODE_STRING Source1, UNICODE_STRING Source2)
@@ -709,7 +805,6 @@ PurgeAllTickets(HANDLE LogonHandle, ULONG PackageId)
return TRUE;
}
-
static BOOL
PurgeTicket2000( HANDLE LogonHandle, ULONG PackageId,
krb5_context context, krb5_creds *cred )
@@ -847,6 +942,116 @@ PurgeTicketXP( HANDLE LogonHandle, ULONG PackageId,
return TRUE;
}
+#ifdef KERB_SUBMIT_TICKET
+static BOOL
+KerbSubmitTicket( HANDLE LogonHandle, ULONG PackageId,
+ krb5_context context, krb5_creds *cred)
+{
+ NTSTATUS Status = 0;
+ NTSTATUS SubStatus = 0;
+ KERB_SUBMIT_TKT_REQUEST * pSubmitRequest;
+ DWORD dwRequestLen;
+ krb5_auth_context auth_context;
+ krb5_keyblock * keyblock = 0;
+ krb5_replay_data replaydata;
+ krb5_data * krb_cred = 0;
+ krb5_error_code rc;
+
+ if (krb5_auth_con_init(context, &auth_context)) {
+ return FALSE;
+ }
+
+ if (krb5_auth_con_setflags(context, auth_context,
+ KRB5_AUTH_CONTEXT_RET_TIME)) {
+ return FALSE;
+ }
+
+ krb5_auth_con_getsendsubkey(context, auth_context, &keyblock);
+ if (keyblock == NULL)
+ krb5_auth_con_getkey(context, auth_context, &keyblock);
+#ifdef TESTING
+ /* do not use this code unless testing the LSA */
+ if (keyblock == NULL) {
+ keyblock = (krb5_keyblock *)malloc(sizeof(krb5_keyblock));
+ keyblock->enctype = ENCTYPE_ARCFOUR_HMAC;
+ keyblock->length = 16;
+ keyblock->contents = (krb5_octet *)malloc(16);
+ keyblock->contents[0] = 0xde;
+ keyblock->contents[1] = 0xad;
+ keyblock->contents[2] = 0xbe;
+ keyblock->contents[3] = 0xef;
+ keyblock->contents[4] = 0xfe;
+ keyblock->contents[5] = 0xed;
+ keyblock->contents[6] = 0xf0;
+ keyblock->contents[7] = 0xd;
+ keyblock->contents[8] = 0xde;
+ keyblock->contents[9] = 0xad;
+ keyblock->contents[10] = 0xbe;
+ keyblock->contents[11] = 0xef;
+ keyblock->contents[12] = 0xfe;
+ keyblock->contents[13] = 0xed;
+ keyblock->contents[14] = 0xf0;
+ keyblock->contents[15] = 0xd;
+ krb5_auth_con_setsendsubkey(context, auth_context, keyblock);
+ }
+#endif
+ rc = krb5_mk_1cred(context, auth_context, cred, &krb_cred, &replaydata);
+ if (rc) {
+ krb5_auth_con_free(context, auth_context);
+ if (keyblock)
+ krb5_free_keyblock(context, keyblock);
+ if (krb_cred)
+ krb5_free_data(context, krb_cred);
+ return FALSE;
+ }
+
+ dwRequestLen = sizeof(KERB_SUBMIT_TKT_REQUEST) + krb_cred->length + (keyblock ? keyblock->length : 0);
+
+ pSubmitRequest = (PKERB_SUBMIT_TKT_REQUEST)malloc(dwRequestLen);
+ memset(pSubmitRequest, 0, dwRequestLen);
+
+ pSubmitRequest->MessageType = KerbSubmitTicketMessage;
+ pSubmitRequest->LogonId.LowPart = 0;
+ pSubmitRequest->LogonId.HighPart = 0;
+ pSubmitRequest->Flags = 0;
+
+ if (keyblock) {
+ pSubmitRequest->Key.KeyType = keyblock->enctype;
+ pSubmitRequest->Key.Length = keyblock->length;
+ pSubmitRequest->Key.Offset = sizeof(KERB_SUBMIT_TKT_REQUEST)+krb_cred->length;
+ } else {
+ pSubmitRequest->Key.KeyType = ENCTYPE_NULL;
+ pSubmitRequest->Key.Length = 0;
+ pSubmitRequest->Key.Offset = 0;
+ }
+ pSubmitRequest->KerbCredSize = krb_cred->length;
+ pSubmitRequest->KerbCredOffset = sizeof(KERB_SUBMIT_TKT_REQUEST);
+ memcpy(((CHAR *)pSubmitRequest)+sizeof(KERB_SUBMIT_TKT_REQUEST),
+ krb_cred->data, krb_cred->length);
+ if (keyblock)
+ memcpy(((CHAR *)pSubmitRequest)+sizeof(KERB_SUBMIT_TKT_REQUEST)+krb_cred->length,
+ keyblock->contents, keyblock->length);
+ krb5_free_data(context, krb_cred);
+
+ Status = LsaCallAuthenticationPackage( LogonHandle,
+ PackageId,
+ pSubmitRequest,
+ dwRequestLen,
+ NULL,
+ NULL,
+ &SubStatus
+ );
+ free(pSubmitRequest);
+ if (keyblock)
+ krb5_free_keyblock(context, keyblock);
+ krb5_auth_con_free(context, auth_context);
+
+ if (FAILED(Status) || FAILED(SubStatus)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+#endif /* KERB_SUBMIT_TICKET */
/*
* A simple function to determine if there is an exact match between two tickets
@@ -1269,6 +1474,41 @@ GetQueryTktCacheResponseXP( HANDLE LogonHandle, ULONG PackageId,
return FALSE;
}
+#ifdef HAVE_CACHE_INFO_EX2
+static BOOL
+GetQueryTktCacheResponseEX2( HANDLE LogonHandle, ULONG PackageId,
+ PKERB_QUERY_TKT_CACHE_EX2_RESPONSE * ppResponse)
+{
+ NTSTATUS Status = 0;
+ NTSTATUS SubStatus = 0;
+
+ KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
+ PKERB_QUERY_TKT_CACHE_EX2_RESPONSE pQueryResponse = NULL;
+ ULONG ResponseSize;
+
+ CacheRequest.MessageType = KerbQueryTicketCacheEx2Message;
+ CacheRequest.LogonId.LowPart = 0;
+ CacheRequest.LogonId.HighPart = 0;
+
+ Status = LsaCallAuthenticationPackage(
+ LogonHandle,
+ PackageId,
+ &CacheRequest,
+ sizeof(CacheRequest),
+ &pQueryResponse,
+ &ResponseSize,
+ &SubStatus
+ );
+
+ if ( !(FAILED(Status) || FAILED(SubStatus)) ) {
+ *ppResponse = pQueryResponse;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+#endif /* HAVE_CACHE_INFO_EX2 */
+
static BOOL
GetMSCacheTicketFromMITCred( HANDLE LogonHandle, ULONG PackageId,
krb5_context context, krb5_creds *creds,
@@ -1443,6 +1683,64 @@ GetMSCacheTicketFromCacheInfoXP( HANDLE LogonHandle, ULONG PackageId,
}
+#ifdef HAVE_CACHE_INFO_EX2
+static BOOL
+GetMSCacheTicketFromCacheInfoEX2( HANDLE LogonHandle, ULONG PackageId,
+ PKERB_TICKET_CACHE_INFO_EX2 tktinfo, PKERB_EXTERNAL_TICKET *ticket)
+{
+ NTSTATUS Status = 0;
+ NTSTATUS SubStatus = 0;
+ ULONG RequestSize;
+ PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;
+ PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;
+ ULONG ResponseSize;
+
+ RequestSize = sizeof(*pTicketRequest) + tktinfo->ServerName.Length;
+
+ pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize);
+ if (!pTicketRequest)
+ return FALSE;
+
+ pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage;
+ pTicketRequest->LogonId.LowPart = 0;
+ pTicketRequest->LogonId.HighPart = 0;
+ pTicketRequest->TargetName.Length = tktinfo->ServerName.Length;
+ pTicketRequest->TargetName.MaximumLength = tktinfo->ServerName.Length;
+ pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1);
+ memcpy(pTicketRequest->TargetName.Buffer,tktinfo->ServerName.Buffer, tktinfo->ServerName.Length);
+ pTicketRequest->CacheOptions = KERB_RETRIEVE_TICKET_CACHE_TICKET;
+ pTicketRequest->EncryptionType = tktinfo->SessionKeyType;
+ pTicketRequest->TicketFlags = 0;
+ if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwardable )
+ pTicketRequest->TicketFlags |= KDC_OPT_FORWARDABLE;
+ if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwarded )
+ pTicketRequest->TicketFlags |= KDC_OPT_FORWARDED;
+ if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_proxiable )
+ pTicketRequest->TicketFlags |= KDC_OPT_PROXIABLE;
+ if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_renewable )
+ pTicketRequest->TicketFlags |= KDC_OPT_RENEWABLE;
+
+ Status = LsaCallAuthenticationPackage(
+ LogonHandle,
+ PackageId,
+ pTicketRequest,
+ RequestSize,
+ &pTicketResponse,
+ &ResponseSize,
+ &SubStatus
+ );
+
+ LocalFree(pTicketRequest);
+
+ if (FAILED(Status) || FAILED(SubStatus))
+ return(FALSE);
+
+ /* otherwise return ticket */
+ *ticket = &(pTicketResponse->Ticket);
+ return(TRUE);
+}
+#endif /* HAVE_CACHE_INFO_EX2 */
+
static krb5_error_code KRB5_CALLCONV krb5_lcc_close
(krb5_context, krb5_ccache id);
@@ -1505,6 +1803,9 @@ typedef struct _krb5_lcc_cursor {
union {
PKERB_QUERY_TKT_CACHE_RESPONSE w2k;
PKERB_QUERY_TKT_CACHE_EX_RESPONSE xp;
+#ifdef HAVE_CACHE_INFO_EX2
+ PKERB_QUERY_TKT_CACHE_EX2_RESPONSE ex2;
+#endif /* HAVE_CACHE_INFO_EX2 */
} response;
unsigned int index;
PKERB_EXTERNAL_TICKET mstgt;
@@ -1719,6 +2020,16 @@ krb5_lcc_start_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cur
return KRB5_FCC_INTERNAL;
}
+#ifdef HAVE_CACHE_INFO_EX2
+ if ( does_query_ticket_cache_ex2() ) {
+ if ( !GetQueryTktCacheResponseEX2(data->LogonHandle, data->PackageId, &lcursor->response.ex2) ) {
+ LsaFreeReturnBuffer(lcursor->mstgt);
+ free(lcursor);
+ *cursor = 0;
+ return KRB5_FCC_INTERNAL;
+ }
+ } else
+#endif /* HAVE_CACHE_INFO_EX2 */
if ( is_windows_xp() ) {
if ( !GetQueryTktCacheResponseXP(data->LogonHandle, data->PackageId, &lcursor->response.xp) ) {
LsaFreeReturnBuffer(lcursor->mstgt);
@@ -1771,6 +2082,33 @@ krb5_lcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
data = (krb5_lcc_data *)id->data;
next_cred:
+#ifdef HAVE_CACHE_INFO_EX2
+ if ( does_query_ticket_cache_ex2() ) {
+ if ( lcursor->index >= lcursor->response.ex2->CountOfTickets ) {
+ if (retval == KRB5_OK)
+ return KRB5_CC_END;
+ else {
+ LsaFreeReturnBuffer(lcursor->mstgt);
+ LsaFreeReturnBuffer(lcursor->response.ex2);
+ free(*cursor);
+ *cursor = 0;
+ return retval;
+ }
+ }
+
+ if ( data->flags & KRB5_TC_NOTICKET ) {
+ CacheInfoEx2ToMITCred( &lcursor->response.ex2->Tickets[lcursor->index++],
+ context, creds);
+ return KRB5_OK;
+ } else {
+ if (!GetMSCacheTicketFromCacheInfoEX2(data->LogonHandle, data->PackageId,
+ &lcursor->response.ex2->Tickets[lcursor->index++],&msticket)) {
+ retval = KRB5_FCC_INTERNAL;
+ goto next_cred;
+ }
+ }
+ } else
+#endif /* HAVE_CACHE_INFO_EX2 */
if ( is_windows_xp() ) {
if ( lcursor->index >= lcursor->response.xp->CountOfTickets ) {
if (retval == KRB5_OK)
@@ -1816,6 +2154,11 @@ krb5_lcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
}
/* convert the ticket */
+#ifdef HAVE_CACHE_INFO_EX2
+ if ( does_query_ticket_cache_ex2() ) {
+ MSCredToMITCred(msticket, lcursor->response.ex2->Tickets[lcursor->index-1].ClientRealm, context, creds);
+ } else
+#endif /* HAVE_CACHE_INFO_EX2 */
if ( is_windows_xp() ) {
MSCredToMITCred(msticket, lcursor->response.xp->Tickets[lcursor->index-1].ClientRealm, context, creds);
} else {
@@ -1848,6 +2191,11 @@ krb5_lcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *curso
if ( lcursor ) {
LsaFreeReturnBuffer(lcursor->mstgt);
+#ifdef HAVE_CACHE_INFO_EX2
+ if ( does_query_ticket_cache_ex2() )
+ LsaFreeReturnBuffer(lcursor->response.ex2);
+ else
+#endif /* HAVE_CACHE_INFO_EX2 */
if ( is_windows_xp() )
LsaFreeReturnBuffer(lcursor->response.xp);
else
@@ -1999,7 +2347,7 @@ krb5_lcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields,
* cache contents until we find the matching service ticket.
*/
PKERB_QUERY_TKT_CACHE_EX_RESPONSE pResponse = 0;
- int i;
+ unsigned int i;
if (!GetQueryTktCacheResponseXP( data->LogonHandle, data->PackageId, &pResponse)) {
kret = KRB5_FCC_INTERNAL;
@@ -2066,6 +2414,12 @@ krb5_lcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
if (!is_windows_2000())
return KRB5_FCC_NOFILE;
+#ifdef KERB_SUBMIT_TICKET
+ /* we can use the new KerbSubmitTicketMessage to store the ticket */
+ if (KerbSubmitTicket( data->LogonHandle, data->PackageId, context, creds ))
+ return KRB5_OK;
+#endif /* KERB_SUBMIT_TICKET */
+
/* If not, lets try to obtain a matching ticket from the KDC */
if ( creds->ticket_flags != 0 && creds->keyblock.enctype != 0 ) {
/* if not, we must try to get a ticket without specifying any flags or etypes */