#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <readpassphrase.h>
#include <DirectoryService/DirectoryService.h>
#ifndef bool
typedef enum { false = 0, true = 1 } bool;
#endif /* bool */
// 32k buffer
#define BUFFERSIZE 32 * 1024
tDirReference DoTinyAuth2(
tDirReference dirRef,
tDirNodeReference nodeRef,
const char *user,
const char *pass,
bool *authResult,
char **resultMsg )
{
long dirStatus = eDSNoErr ;
tDataBufferPtr authBuffer ;
tDataBufferPtr respBuffer ;
tContextData authContext ;
tDataNodePtr authType ;
long userLen = strlen( user );
long passLen = strlen( pass );
long authBufferLen ;
authBufferLen = sizeof(long) + userLen
+ sizeof(long) + passLen ;
authBuffer = dsDataBufferAllocate( dirRef, authBufferLen );
respBuffer = dsDataBufferAllocate( dirRef, BUFFERSIZE ); //dummy
#if ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 )
dsFillAuthBuffer( authBuffer, 2,
userLen, user,
passLen, pass );
#else // Tiger or eariler
{
long pos = 0;
pos = 0;
memcpy( &(authBuffer->fBufferData[pos]), &userLen, sizeof(long) );
pos += sizeof(long);
memcpy( &(authBuffer->fBufferData[pos]), user, userLen );
pos += userLen ;
memcpy( &(authBuffer->fBufferData[pos]), &passLen, sizeof(long) );
pos += sizeof(long);
memcpy( &(authBuffer->fBufferData[pos]), pass, passLen );
pos += passLen ;
authBuffer->fBufferLength = pos ;
}
#endif
authType = dsDataNodeAllocateString( dirRef, kDSStdAuthNodeNativeNoClearText );
dirStatus = dsDoDirNodeAuth( nodeRef, authType, true, authBuffer, respBuffer, &authContext );
switch( dirStatus )
{
case eDSNoErr: // Auth Success
*authResult = true ;
if( resultMsg ) *resultMsg = "Auth Success." ;
break;
case eDSAuthFailed : // Auth Fail
*authResult = false ;
if( resultMsg ) *resultMsg = "Auth Failure." ;
break;
case eDSAuthMethodNotSupported : // Auth not supported
*authResult = false ;
if( resultMsg ) *resultMsg = "This Auth Type not supported." ;
break;
default:
*authResult = false ;
if( resultMsg ) *resultMsg = "unknown error." ;
break;
}
dsDataBufferDeAllocate ( dirRef, authBuffer );
dsDataBufferDeAllocate ( dirRef, respBuffer );
return dirStatus;
}
int main( int argc, char *argv[] )
{
int ret = 0 ;
long dirStatus = eDSNoErr ;
tDirReference dirRef = 0 ;
tDirNodeReference nodeRef = 0 ;
const char *nodepath = (argc > 1 ? argv[1] : "/Local/Default" );
tDataListPtr nodeName = NULL ;
const char *user = (argc > 2 ? argv[2] : "me" );
char pass[BUFFERSIZE] ; // tenuki
char *resultMsg = NULL ;
bool isAuthOK = false;
// open OD
dirStatus = dsOpenDirService( &dirRef );
if( dirStatus != eDSNoErr ) goto errexit ;
// open node
nodeName = dsBuildFromPath( dirRef, nodepath, "/" );
if( nodeName == NULL )
{
fprintf( stderr, "name buffer allocate error\n") ;
ret = 1;
goto toexit;
}
dirStatus = dsOpenDirNode( dirRef, nodeName, &nodeRef );
if( dirStatus != eDSNoErr ) goto errexit ;
if( NULL == readpassphrase("Passwd: ", pass, sizeof( pass ), 0 ) )
goto errexit ;
dirStatus = DoTinyAuth2( dirRef, nodeRef, user, pass, &isAuthOK, &resultMsg );
printf( "user %s, auth %s.\n", user, ( isAuthOK ? "OK" : "NG" ) );
if( resultMsg != NULL )
printf( "msg = %s (%d)\n", resultMsg, dirStatus );
goto toexit;
errexit:
ret = 1;
fprintf( stderr, "errocode = %d\n", dirStatus );
toexit:
if( nodeRef != 0 )
dsCloseDirNode( nodeRef );
if( dirRef != 0 )
dsCloseDirService( dirRef );
exit(ret);
}