@@ -125,18 +125,47 @@ struct krb5_req {
125125
126126static krb5_context krb5_error_ctx ;
127127
128+ static inline void debug_and_log (int level , int line ,
129+ krb5_error_code krb5_error ,
130+ const char * krb5_error_msg )
131+ {
132+ DEBUG (level , "%d: [%d][%s]\n" , line , krb5_error , krb5_error_msg );
133+ if (level & (SSSDBG_CRIT_FAILURE | SSSDBG_FATAL_FAILURE )) {
134+ sss_log (SSS_LOG_ERR , "%s" , krb5_error_msg );
135+ }
136+
137+ return ;
138+ }
139+
128140#define KRB5_CHILD_DEBUG_INT (level , errctx , krb5_error ) do { \
129141 const char *__krb5_error_msg; \
130142 __krb5_error_msg = sss_krb5_get_error_message(errctx, krb5_error); \
131- DEBUG(level, "%d: [%d][%s]\n", __LINE__, krb5_error, __krb5_error_msg); \
132- if (level & (SSSDBG_CRIT_FAILURE | SSSDBG_FATAL_FAILURE)) { \
133- sss_log(SSS_LOG_ERR, "%s", __krb5_error_msg); \
134- } \
143+ debug_and_log(level, __LINE__, krb5_error, __krb5_error_msg); \
135144 sss_krb5_free_error_message(errctx, __krb5_error_msg); \
136145} while(0)
137146
138147#define KRB5_CHILD_DEBUG (level , error ) KRB5_CHILD_DEBUG_INT(level, krb5_error_ctx, error)
139148
149+ static bool debug_and_check_if_pin_locked_error (krb5_context ctx , int level ,
150+ krb5_error_code krb5_error )
151+ {
152+ const char * krb5_error_msg ;
153+ bool res = false;
154+
155+ /* sss_krb5_free_error_message() never returns NULL */
156+ krb5_error_msg = sss_krb5_get_error_message (ctx , krb5_error );
157+
158+ if (strstr (krb5_error_msg , "pin locked" ) != NULL ) {
159+ res = true;
160+ }
161+
162+ debug_and_log (level , __LINE__ , krb5_error , krb5_error_msg );
163+
164+ sss_krb5_free_error_message (ctx , krb5_error_msg );
165+
166+ return res ;
167+ }
168+
140169static krb5_error_code get_tgt_times (krb5_context ctx , const char * ccname ,
141170 krb5_principal server_principal ,
142171 krb5_principal client_principal ,
@@ -2404,6 +2433,7 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
24042433 char * cc_name ;
24052434 int ret ;
24062435 char * identity = NULL ;
2436+ const uint32_t user_info_pin_locked = SSS_PAM_USER_INFO_PIN_LOCKED ;
24072437
24082438 kerr = sss_krb5_get_init_creds_opt_set_expire_callback (kr -> ctx , kr -> options ,
24092439 sss_krb5_expire_callback_func ,
@@ -2469,7 +2499,32 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
24692499 return 0 ;
24702500 } else {
24712501 if (kerr != 0 ) {
2472- KRB5_CHILD_DEBUG (SSSDBG_CRIT_FAILURE , kerr );
2502+ /* If
2503+ * - during authentication
2504+ * - the pre-authentication failed
2505+ * - while Smartcard authentication was possible
2506+ * - and Smartcard credentials were available
2507+ * check if the PIN might be locked.
2508+ * Must be called before/instead of KRB5_CHILD_DEBUG because
2509+ * krb5_get_error_message() might only return the proper error
2510+ * message at the first call. */
2511+ if (kr -> pd -> cmd == SSS_PAM_AUTHENTICATE
2512+ && kerr == KRB5_PREAUTH_FAILED
2513+ && kr -> pkinit_prompting == true
2514+ && IS_SC_AUTHTOK (kr -> pd -> authtok ) ) {
2515+ if (debug_and_check_if_pin_locked_error (kr -> ctx ,
2516+ SSSDBG_CRIT_FAILURE , kerr ) ) {
2517+ ret = pam_add_response (kr -> pd , SSS_PAM_USER_INFO ,
2518+ sizeof (uint32_t ),
2519+ (const uint8_t * ) & user_info_pin_locked );
2520+ if (ret != EOK ) {
2521+ DEBUG (SSSDBG_OP_FAILURE ,
2522+ "Failed to add PIN locked message.\n" );
2523+ }
2524+ }
2525+ } else {
2526+ KRB5_CHILD_DEBUG (SSSDBG_CRIT_FAILURE , kerr );
2527+ }
24732528
24742529 if (kerr == EAGAIN ) {
24752530 /* The most probable reason for krb5_get_init_creds_password()
0 commit comments