X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/2965425374ca4413339436c2f706f7b5508402e2..ce0ac947b4708d0bc1c7e6789b3e1f3bfc80d6e9:/checkpw/checkpw.c diff --git a/checkpw/checkpw.c b/checkpw/checkpw.c index d0a0ef76..f300addf 100644 --- a/checkpw/checkpw.c +++ b/checkpw/checkpw.c @@ -65,6 +65,7 @@ typedef struct sComData unsigned long fPID; unsigned long fPort; unsigned long fIPAddress; + mach_msg_audit_trailer_t fTail; sObject obj[ 10 ]; char data[ 1 ]; } sComData; @@ -86,7 +87,8 @@ typedef struct sIPCMsg unsigned long fPort; sObject obj[ 10 ]; char fData[ kIPCMsgLen ]; - mach_msg_security_trailer_t fTail; + mach_msg_audit_trailer_t fTail; // this is the largest trailer struct + // we have the bucket large enough to receive it } sIPCMsg; typedef enum { @@ -99,21 +101,27 @@ enum eDSServerCalls { }; // end copied from SharedConsts.h +int checkpw_internal( const struct passwd* pw, const char* password ); + int checkpw( const char* userName, const char* password ) { struct passwd* pw = NULL; int status; + + // Check username, NULL can crash in getpwnam + if (!userName) + return CHECKPW_UNKNOWNUSER; pw = getpwnam( userName ); if (pw == NULL) return CHECKPW_UNKNOWNUSER; - status = checkpw_internal(userName, password, pw); + status = checkpw_internal(pw, password); endpwent(); return status; } -int checkpw_internal( const char* userName, const char* password, const struct passwd* pw ) +int checkpw_internal( const struct passwd* pw, const char* password ) { int siResult = CHECKPW_FAILURE; kern_return_t result = err_none; @@ -138,6 +146,12 @@ int checkpw_internal( const char* userName, const char* password, const struct p break; } + // check password, NULL crashes crypt() + if (!password) + { + siResult = CHECKPW_BADPASSWORD; + break; + } // Correct password hash if (strcmp(crypt(password, pw->pw_passwd), pw->pw_passwd) == 0) { siResult = CHECKPW_SUCCESS; @@ -178,14 +192,24 @@ int checkpw_internal( const char* userName, const char* password, const struct p msg->obj[0].offset = offsetof(struct sComData, data); // User Name - len = strlen( userName ); + len = strlen( pw->pw_name ); + if (curr + len + sizeof(unsigned long) > kIPCMsgLen) + { + siResult = CHECKPW_FAILURE; + break; + } memcpy( &(msg->fData[ curr ]), &len, sizeof( unsigned long ) ); curr += sizeof( unsigned long ); - memcpy( &(msg->fData[ curr ]), userName, len ); + memcpy( &(msg->fData[ curr ]), pw->pw_name, len ); curr += len; // Password len = strlen( password ); + if (curr + len + sizeof(unsigned long) > kIPCMsgLen) + { + siResult = CHECKPW_FAILURE; + break; + } memcpy( &(msg->fData[ curr ]), &len, sizeof( unsigned long ) ); curr += sizeof ( unsigned long ); memcpy( &(msg->fData[ curr ]), password, len ); @@ -194,7 +218,7 @@ int checkpw_internal( const char* userName, const char* password, const struct p msg->obj[0].length = curr; msg->fHeader.msgh_bits = MACH_MSGH_BITS( MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND ); - msg->fHeader.msgh_size = sizeof( sIPCMsg ) - sizeof( mach_msg_security_trailer_t ); + msg->fHeader.msgh_size = sizeof( sIPCMsg ) - sizeof( mach_msg_audit_trailer_t ); msg->fHeader.msgh_id = kCheckUserNameAndPassword; msg->fHeader.msgh_remote_port = serverPort; msg->fHeader.msgh_local_port = replyPort; @@ -216,7 +240,9 @@ int checkpw_internal( const char* userName, const char* password, const struct p // get reply memset( msg, 0, kIPCMsgLen ); - result = mach_msg( (mach_msg_header_t *)msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, + result = mach_msg( (mach_msg_header_t *)msg, + MACH_RCV_MSG | MACH_RCV_TIMEOUT | + MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0), 0, kIPCMsgSize, replyPort, 300 * 1000, MACH_PORT_NULL ); if ( result != MACH_MSG_SUCCESS ) { @@ -246,8 +272,11 @@ int checkpw_internal( const char* userName, const char* password, const struct p msg = NULL; } + // deallocate the serverPort + mach_port_deallocate( mach_task_self(), serverPort); + if ( replyPort != 0 ) - mach_port_deallocate( mach_task_self(), replyPort ); + mach_port_destroy( mach_task_self(), replyPort ); return siResult;