您的位置:首页 > 运维架构

使用OPENLDAP C API修改 win2003 AD域(Active Directory)用户密码

2014-01-08 16:04 936 查看
参考:/article/2838851.html

参考:http://www.121.name/LDAP.html

参考:http://pig.made-it.com/pig-adusers.html

首先要在win2003上安装AD域,并且支持SSL,参见:

win2003 AD域 支持 LDAP SSL

上源码:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

#define LDAP_TYPELEN    128
#define LDAP_VALUELEN    256

#define ADMIN           "CN=Administrator,CN=Users,DC=domain,DC=com"      // AD administrator dn
#define ADMIN_PASSWORD  "password"
#define AD_DOMAINNAME   "ll-u4b5ul9ztwm9.cylan.lfm.com"
#define AD_PORT         389
#define AD_SSLPORT      636

#define DEBUG           0

#define OPT_NONSSL      "0"
#define OPT_SSL         "1"
#define OPT_TLS         "2"
#define SCHEME_LDAP     "ldap"
#define SCHEME_LDAPS    "ldaps"

#define DST_DN          "CN=usertest,CN=Users,DC=domain,DC=com"            // destination dn

#ifdef __cplusplus
extern "C"
{
#endif
#include <ldap.h>

#define DNLEN 256

LDAP* ldap_init(char*ip,int port);
int ldap_simple_bind_s(LDAP *ld, const char *who, const char *passwd);
int ldap_search_s(LDAP*ld,char* base, int scope,char* filter, char*attrs[], int attrsonly,LDAPMessage** res);
int ldap_unbind_s(LDAP *ld);
int ldap_modify_s(  LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods );

#ifdef __cplusplus
}
#endif

static void freeLdap(LDAP *ldap)
{
ldap_unbind_s(ldap);
}

static void timeout(int signo,siginfo_t *si, void *unused)
{
return;
}

static LDAP* initLdap( int USE_SSL )
{
LDAP* ld;
//ldap init timer 10 seconds
int timer = 10;
struct sigaction sa;
int i_ret = 0;

sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = timeout;
if (-1 == sigaction(SIGALRM,&sa,NULL))
{
printf("set timeout action in ldapserver failed\n");
}
alarm( timer );

if( USE_SSL != 0 )
{
char psz_secure_url[128];
if(USE_SSL == 1)
{
sprintf(psz_secure_url, "%s://%s:%d", SCHEME_LDAPS, AD_DOMAINNAME, AD_SSLPORT );
}
else
{
sprintf(psz_secure_url, "%s://%s:%d", SCHEME_LDAP, AD_DOMAINNAME, AD_PORT );
}

i_ret = ldap_initialize(&ld, psz_secure_url);
if ( i_ret != LDAP_SUCCESS || ld == NULL )
{
fprintf(stderr, "ldap_initialize: errno %d : %s\n", i_ret, ldap_err2string( i_ret ));
return NULL;
}
fprintf(stderr, "SSL/TLS URL: %s\n", psz_secure_url);

// only at Session Handle level!!!! which means the first parameter must be the LDAP* handle
const int i_version = LDAP_VERSION3;
i_ret = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &i_version );
if ( i_ret != LDAP_SUCCESS )
{
fprintf(stderr, "set_option LDAP_OPT_PROTOCOL_VERSION errno %d : %s\n", i_ret, ldap_err2string( i_ret ) );
return NULL;
}

// only at GOBAL level!!!! which means the first parameter must be NULL
char* psz_certfile = "./testca1.cer";   // AD server CA
i_ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, psz_certfile);
if ( i_ret != LDAP_SUCCESS )
{
fprintf(stderr, "set_option LDAP_OPT_X_TLS_CACERTFILE errno %d : %s\n", i_ret, ldap_err2string( i_ret ));
return NULL;
}

if(USE_SSL == 2)
{
i_ret = ldap_start_tls_s(ld, NULL, NULL);
if ( i_ret != LDAP_SUCCESS )
{
fprintf(stderr, "ldap_start_tls: errno %d : %s\n", i_ret, ldap_err2string( i_ret ));
return NULL;
}
}

}
else
{
fprintf( stderr, "Unsecure URL: ldap://%s:%d/\n", AD_DOMAINNAME, AD_PORT );
i_ret = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &i_version );
if ( i_ret != LDAP_SUCCESS )
{
fprintf(stderr, "set_option LDAP_OPT_PROTOCOL_VERSION errno %d : %s\n", i_ret, ldap_err2string( i_ret ) );
return NULL;
}
if ( NULL == ( ld = ldap_init( AD_DOMAINNAME, AD_PORT ) ) )
{
printf( "initial LDAP server %s failed\n", AD_DOMAINNAME );
return NULL;
}
}

if ( ( i_ret = ldap_simple_bind_s( ld, ADMIN, ADMIN_PASSWORD ) ) != LDAP_SUCCESS )
{

fprintf( stderr, "bind LDAP server %s failed, errno %d : %s\n", AD_DOMAINNAME, i_ret, ldap_err2string( i_ret ) );
freeLdap( ld );
return NULL;
}
return ld;
}

int main( int argc, char **argv )
{
LDAP* ld = NULL;

char *psz_filter = "(objectclass=user)";
int i_debug_flag1 = -1; // LDAP_DEBUG_ANY ;
LDAPMessage *p_ldapmsg = NULL;
int i_ret = 0;
int USE_SSL = 0;//default, non-ssl

if ( argc != 4 )
{
printf( "Usage: \n"
"\t%s SSLFLAG operation newpassword\n"
"\t( operation:\tadd: %d, modify: %d, delete: %d \n"
"\t  SSLFLAG:\t0: normal connection, 1: use ssl connection, 2: tls connection )\n"
"\tfor example:\n"
"\t\t%s 1 2 newpasswordvalue\n",
argv[0], LDAP_MOD_ADD, LDAP_MOD_REPLACE, LDAP_MOD_DELETE, argv[0] );
return -1;
}

// get connection flag
if(strcmp(argv[1], OPT_NONSSL) == 0)
{
fprintf(stderr, "Using unsecure connection\n");
USE_SSL = 0;
}
else if (strcmp(argv[1], OPT_SSL) == 0)
{
fprintf(stderr, "Using non-standard SSL connection\n");
USE_SSL = 1;
}
else if (strcmp(argv[1], OPT_TLS) == 0)
{
fprintf(stderr, "Using standard TLS connection\n");
USE_SSL = 2;
}
else
{
fprintf(stderr, "please enter connection type: 0 for NonSSL, 1 for SSL, 2 for TLS\n");
return (1);
}

if ( DEBUG )
{
i_ret = ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &i_debug_flag1 );
if ( i_ret != LDAP_SUCCESS)
{
fprintf(stderr, "set_option LDAP_OPT_DEBUG_LEVEL errno %d : %s\n", i_ret, ldap_err2string( i_ret ) );
return -5;
}
}

if ( NULL == ( ld = initLdap( USE_SSL ) ) )
return -3; // connect error

// begin query infor
i_ret = ldap_search_s( ld, DST_DN, LDAP_SCOPE_SUBTREE, psz_filter, NULL, 0, &p_ldapmsg );
if ( LDAP_SIZELIMIT_EXCEEDED == i_ret )
{
return -4;
}
else if ( i_ret != LDAP_SUCCESS && i_ret != LDAP_OPERATIONS_ERROR )
return -2; // basedn error

if ( NULL == p_ldapmsg )
return -1;

int i_count = 0;
if ((i_count = ldap_count_entries(ld,p_ldapmsg)) > 0)
{
LDAPMessage *ent = NULL;
for ( ent = ldap_first_entry( ld, p_ldapmsg ); ent != NULL; ent = ldap_next_entry( ld, ent ) )
{
struct berval **pp_verval;
char *pp_attr[] = { "distinguishedName", "cn", "unicodePwd", "DBCSPwd", "userAccountControl",
"supplementalCredentials", "dSHeuristics", "fUserPwdSupport", "supplementalCredentials",
"dSHeuristics", NULL };
char *p_attr = NULL;
int i_index = 0;
for ( p_attr = pp_attr[0]; ( p_attr = pp_attr[i_index] ) != NULL; i_index ++ )
{
pp_verval = ldap_get_values_len( ld, ent, p_attr );
do
{
printf( "get attribute %s = ", p_attr );
if( ldap_count_values_len( pp_verval ) == 0 )
{
printf( "\n" );
continue;
}
printf( "%s\n", ( *pp_verval )->bv_val );
} while(0);
}
ldap_value_free_len( pp_verval );
}
}
// end query info

// set mod value
char *psz_newpasswd = argv[3];
char psz_newpasswd_quotes[128] = {0};
char psz_newpasswd_unicode[256] = {0};
struct berval bvalnew;
struct berval *bvalsnew[2];
LDAPMod mod;
LDAPMod *mods[3];

snprintf( psz_newpasswd_quotes, sizeof( psz_newpasswd_quotes ), "\"%s\"", psz_newpasswd );
int i_index = 0;
for ( i_index = 0; i_index < strlen( psz_newpasswd_quotes ); i_index ++ )
{
psz_newpasswd_unicode[i_index * 2] = psz_newpasswd_quotes[i_index];
}

bvalnew.bv_val = psz_newpasswd_unicode;
bvalnew.bv_len = strlen( psz_newpasswd_quotes ) * 2;

bvalsnew[0] = &bvalnew;
bvalsnew[1] = NULL;

mod.mod_vals.modv_bvals = bvalsnew;
mod.mod_type = (char *) "unicodePwd";
mod.mod_op = atoi( argv[2] ) | LDAP_MOD_BVALUES;

mods[0] = &mod;
mods[1] = NULL;

// run modify function
i_ret = ldap_modify_s( ld, DST_DN, mods );
printf( "ldap_modify_ext_s, i_ret: %d, %s\n", i_ret, ldap_err2string( i_ret ) );

return 0;
}


编译:

# gcc -g -Wall -Werror ./sslldappass.c -o ./sslldappass -lldap

运行:

# ./sslldappass 1 2 XXXXXXXX

这里密码要注意复杂度

本程序可以用来修改任何属性,只是除unicodePwd外的其它属性不需要转换成UTF16LE。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: