]> git.saurik.com Git - apple/security.git/blobdiff - checkpw/checkpw.c
Security-177.tar.gz
[apple/security.git] / checkpw / checkpw.c
index d0a0ef761597e7feaf406fb14f9f0c7ce774d7ef..f300addfb1e2c423226556e9de66aca2815d0844 100644 (file)
@@ -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;