Index: /branches/rel_apv_10_7/usr/click/lib/libexauth/auth_ext.c
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libexauth/auth_ext.c	(revision 39496)
+++ /branches/rel_apv_10_7/usr/click/lib/libexauth/auth_ext.c	(working copy)
@@ -36,11 +36,15 @@
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 #include <openssl/opensslv.h>
+#include <openssl/md5.h>
+#include <openssl/rand.h>
 
 #include "auth_ext.h"
 #include "auth_ext_cli.h"
 #include "auth_ext_ipc.h"
 
+#include "taclib_private.h"
+
 /* Global Variables */
 extern exauth_conf_t g_exauth_conf;
 extern exauth_conf_t *shm_p;
@@ -854,6 +858,29 @@
 	return 0;
 }
 
+/*generate the chap digest*/
+void
+digest_chap(unsigned char *digest, unsigned char id,
+				 const char *pass, size_t pass_len,
+				 unsigned char *challenge, size_t challenge_len)
+{
+	ssize_t check;
+
+	check = RAND_bytes(challenge, challenge_len);
+	if (check != 1)
+	{
+		fprintf(stderr, "RAND_bytes() failed\n");
+		exit(1);
+	}
+
+	MD5_CTX ctx;
+	MD5_Init(&ctx);
+	MD5_Update(&ctx, &id, 1);
+	MD5_Update(&ctx, pass, pass_len);
+	MD5_Update(&ctx, challenge, challenge_len);
+	MD5_Final(digest, &ctx);
+}
+
 /*
  * There seems a problem in tac_send_authen() of libtacplus
  * for it mistakenly implemented the "secret" assigned to the 1st server
@@ -869,6 +896,9 @@
 	struct tac_handle *th = NULL;
 	char msg[256];
 
+	int authen_type = g_exauth_conf.exauth_servers[server_num].authen_type;
+	char author_service[110]; // "service=%s"
+
 	/*the return value of tac_x response type*/
 	int ret_type = 0;
 	int ret_value = EXT_AUTH_FAILED;
@@ -913,7 +943,7 @@
 
 
 	/*create a tac_x request*/
-	if (tac_create_authen(th, TAC_AUTHEN_LOGIN, TAC_AUTHEN_TYPE_ASCII,
+	if (tac_create_authen(th, TAC_AUTHEN_LOGIN, authen_type,
 	                      TAC_AUTHEN_SVC_LOGIN) < 0) {
 		tac_close(th);
 		exau_log("auth_one_tacx_server() failed\n");
@@ -927,28 +957,53 @@
 		return EXT_AUTH_FAILED;
 	}
 
+	if (authen_type == TAC_AUTHEN_TYPE_CHAP) {
+		unsigned char challenge[MD5_DIGEST_LENGTH];
+		unsigned char digest[MD5_DIGEST_LENGTH];
+		unsigned char chap_id = 5;
+
+		digest_chap(digest, chap_id,
+					password, strlen(password),
+					challenge, sizeof(challenge));
+
+		u_int token_len = sizeof(chap_id) + sizeof(challenge) + sizeof(digest);
+		unsigned char token[token_len];
+
+		// build the CHAP challenge packet
+		memcpy(token, &chap_id, sizeof(chap_id));
+		memcpy(token + sizeof(chap_id), challenge, sizeof(challenge));
+		memcpy(token + sizeof(chap_id) + sizeof(challenge), digest, sizeof(digest));
+
+		tac_set_data(th, token, sizeof(token));
+
+	} else if (authen_type == TAC_AUTHEN_TYPE_PAP) {
+		tac_set_data(th, password, strlen(password));
+	}
+
 	/*send the START packet and check the response*/
 	ret_type = TAC_AUTHEN_STATUS(tac_send_authen(th));
 
-	/*get the ret_type string*/
-	check_tac_x_type(ret_type, msg);
+	if (authen_type == TAC_AUTHEN_TYPE_ASCII) {
+		/*get the ret_type string*/
+		check_tac_x_type(ret_type, msg);
 
-	/*expected the response should be TAC_AUTHEN_STATUS_GETPASS*/
-	if (ret_type != TAC_AUTHEN_STATUS_GETPASS) {
-		tac_close(th);
-		exau_log("auth_one_tacx_server(): expect TAC_AUTHEN_STATUS_GETPASS, but received %s\n", msg);
-		return EXT_AUTH_FAILED;
-	}
+		/*expected the response should be TAC_AUTHEN_STATUS_GETPASS*/
+		if (ret_type != TAC_AUTHEN_STATUS_GETPASS) {
+			tac_close(th);
+			exau_log("auth_one_tacx_server(): expect TAC_AUTHEN_STATUS_GETPASS, but received %s\n", msg);
+			return EXT_AUTH_FAILED;
+		}
 
-	/*attache the PASSWD to the CONTINUE packet*/
-	if (tac_set_msg(th, password) < 0) {
-		tac_close(th);
-		exau_log("auth_one_tacx_server() failed\n");
-		return EXT_AUTH_FAILED;
-	}
+		/*attache the PASSWD to the CONTINUE packet*/
+		if (tac_set_msg(th, password) < 0) {
+			tac_close(th);
+			exau_log("auth_one_tacx_server() failed\n");
+			return EXT_AUTH_FAILED;
+		}
 
-	/*send the CONTINUED packet and check the response*/
-	ret_type = TAC_AUTHEN_STATUS(tac_send_authen(th));
+		/*send the CONTINUED packet and check the response*/
+		ret_type = TAC_AUTHEN_STATUS(tac_send_authen(th));
+	}
 
 	/*get the ret_type string*/
 	check_tac_x_type(ret_type, msg);
@@ -964,26 +1019,25 @@
 	}
 
 	/*start tac_plus authorization*/
-	if (tac_create_author(th, TAC_AUTHEN_METH_NONE, TAC_AUTHEN_TYPE_ASCII,
+	if (tac_create_author(th, TAC_AUTHEN_METH_TACACSPLUS, authen_type,
 	                      TAC_AUTHEN_SVC_LOGIN) < 0) {
 		tac_close(th);
 		exau_log("tac_create_author() failed\n");
 		return EXT_AUTH_FAILED;
 	}
 
+	// set minor version to 0
+	th->request.version = th->request.version & (~1);
+
 	if (tac_set_user(th, username) < 0) {
 		tac_close(th);
 		exau_log("tac_set_user() failed\n");
 		return EXT_AUTH_FAILED;
 	}
 
-	if (tac_set_av(th, 1, "service=shell") < 0) {
-		tac_close(th);
-		exau_log("tac_set_av() failed\n");
-		return EXT_AUTH_FAILED;
-	}
-
-	if (tac_set_av(th, 2, "cmd*") < 0) {
+	snprintf(author_service, sizeof(author_service), "service=%s",
+	         g_exauth_conf.exauth_servers[server_num].author_service);
+	if (tac_set_av(th, 1, author_service) < 0) {
 		tac_close(th);
 		exau_log("tac_set_av() failed\n");
 		return EXT_AUTH_FAILED;
Index: /branches/rel_apv_10_7/usr/click/lib/libexauth/auth_ext_cli.h
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libexauth/auth_ext_cli.h	(revision 39496)
+++ /branches/rel_apv_10_7/usr/click/lib/libexauth/auth_ext_cli.h	(working copy)
@@ -56,8 +56,8 @@
 typedef enum exau_method {
 	METHOD_RADIUS,
 	METHOD_TAC_X,
-        METHOD_LDAP,
-        METHOD_LDAPS
+	METHOD_LDAP,
+	METHOD_LDAPS
 } enum_exau_method;
 
 #define false 0
@@ -72,9 +72,11 @@
 	char secret[SECRET_LEN];
 	unsigned short timeout;
 	unsigned short max_retry;
-        char dn[DN_LEN];
-        char memberOf[MEMBEROF_LEN];
-        bool verifyCert;
+	char dn[DN_LEN];
+	char memberOf[MEMBEROF_LEN];
+	bool verifyCert;
+	int authen_type;
+	char author_service[101];
 } exauth_server_t;
 
 /*the structure wrapper*/
Index: /branches/rel_apv_10_7/usr/click/lib/libexauth/auth_ext_cli.c
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libexauth/auth_ext_cli.c	(revision 39496)
+++ /branches/rel_apv_10_7/usr/click/lib/libexauth/auth_ext_cli.c	(working copy)
@@ -33,6 +33,8 @@
 #include "auth_ext_cli.h"
 #include "auth_ext_ipc.h"
 
+#include "taclib.h"
+
 /* Global Variables */
 exauth_conf_t g_exauth_conf;
 exauth_conf_t *shm_p = NULL;
@@ -297,14 +299,14 @@
 
 /*configure an exauth tcacs server*/
 int
-exauth_tacacs_server(char *host, uint16_t port, char *secret, char *cipher_flag)
+exauth_tacacs_server(char *host, uint16_t port, char *secret, char* authen_type, char* author_service, char *cipher_flag)
 {
         char *id = "es02";
 	int id_num = -1;
 	char *str_num = NULL, *ep = NULL;
 
 
-	if (id == NULL || host == NULL || secret == NULL)
+	if (id == NULL || host == NULL || secret == NULL || authen_type == NULL || author_service == NULL)
 	{
 		printf ("%s failed\n",CLI_EXAUTH_SERVER);
 		return -1;
@@ -356,6 +358,28 @@
 	strncpy(g_exauth_conf.exauth_servers[id_num].secret, secret, SECRET_LEN - 1);
 	g_exauth_conf.exauth_servers[id_num].secret[SECRET_LEN - 1] = '\0';
 
+	/*check and assign authen_type*/
+	if (strcmp(authen_type, "ASCII") == 0) {
+		g_exauth_conf.exauth_servers[id_num].authen_type = TAC_AUTHEN_TYPE_ASCII;
+	}
+	else if (strcmp(authen_type, "PAP") == 0) {
+		g_exauth_conf.exauth_servers[id_num].authen_type = TAC_AUTHEN_TYPE_PAP;
+	}
+	else if (strcmp(authen_type, "CHAP") == 0) {
+		g_exauth_conf.exauth_servers[id_num].authen_type = TAC_AUTHEN_TYPE_CHAP;
+	}
+	else {
+		printf ("%s | %s | %s\n", "ASCII", "PAP", "CHAP");
+		return 0;
+	}
+
+	/*assign author_service*/
+	if (strlen(g_exauth_conf.exauth_servers[id_num].author_service) > sizeof(g_exauth_conf.exauth_servers[id_num].author_service) - 1) {
+		printf("author_service too long, max %zu\n", sizeof(g_exauth_conf.exauth_servers[id_num].author_service) - 1);
+		return 0;
+	}
+	strncpy(g_exauth_conf.exauth_servers[id_num].author_service, author_service, sizeof(g_exauth_conf.exauth_servers[id_num].author_service) - 1);
+	g_exauth_conf.exauth_servers[id_num].author_service[sizeof(g_exauth_conf.exauth_servers[id_num].author_service) - 1] = '\0';
 
 	/*assign timeout and maxretyr*/
 	if (g_exauth_conf.exau_method == METHOD_RADIUS)
@@ -795,7 +819,32 @@
 	{
 		if (g_exauth_conf.exauth_servers[i].id && g_exauth_conf.exauth_servers[i].id[0] != '\0')
 		{
-                    if (!strcmp (g_exauth_conf.exauth_servers[i].id, "es03")) {
+			if (!strcmp (g_exauth_conf.exauth_servers[i].id, "es02")) {
+				char *authen_type_str;
+				switch (g_exauth_conf.exauth_servers[i].authen_type) {
+					case TAC_AUTHEN_TYPE_ASCII:
+						authen_type_str = "ASCII";
+						break;
+					case TAC_AUTHEN_TYPE_PAP:
+						authen_type_str = "PAP";
+						break;
+					case TAC_AUTHEN_TYPE_CHAP:
+						authen_type_str = "CHAP";
+						break;
+					default:
+						authen_type_str = "ASCII";
+						break;
+				}
+				printf ("%s %s \"%s\" %d \"%s\" \"%s\" \"%s\"\n",
+					CLI_EXAUTH_SERVER,
+					g_exauth_conf.exauth_servers[i].id,
+					g_exauth_conf.exauth_servers[i].host,
+					g_exauth_conf.exauth_servers[i].port,
+					"*****",
+					authen_type_str,
+					g_exauth_conf.exauth_servers[i].author_service
+				);
+                    } else if (!strcmp (g_exauth_conf.exauth_servers[i].id, "es03")) {
                         printf ("%s %s \"%s\" %d \"%s\" \"%s\" \n",
                                     CLI_EXAUTH_SERVER,
                                     g_exauth_conf.exauth_servers[i].id,
@@ -950,7 +999,34 @@
 	{
 		if (g_exauth_conf.exauth_servers[i].id && g_exauth_conf.exauth_servers[i].id[0] != '\0')
 		{
-                    if (g_exauth_conf.exau_method == METHOD_LDAP) {
+			if (g_exauth_conf.exau_method == METHOD_TAC_X) {
+				encrypt_secret((unsigned char *)(g_exauth_conf.exauth_servers[i].secret), encrypted_secret);
+				char *authen_type_str;
+				switch (g_exauth_conf.exauth_servers[i].authen_type) {
+					case TAC_AUTHEN_TYPE_ASCII:
+						authen_type_str = "ASCII";
+						break;
+					case TAC_AUTHEN_TYPE_PAP:
+						authen_type_str = "PAP";
+						break;
+					case TAC_AUTHEN_TYPE_CHAP:
+						authen_type_str = "CHAP";
+						break;
+					default:
+						authen_type_str = "ASCII";
+						break;
+				}
+				buf_offset += sprintf (conf_buf + buf_offset, "%s %s \"%s\" %d \"%s\" \"%s\" \"%s\" \"%s\"\n",
+					CLI_EXAUTH_SERVER,
+					g_exauth_conf.exauth_servers[i].id,
+					g_exauth_conf.exauth_servers[i].host,
+					g_exauth_conf.exauth_servers[i].port,
+					encrypted_secret,
+					authen_type_str,
+					g_exauth_conf.exauth_servers[i].author_service,
+					AAA_SECRET_ENCRYPTED
+				);
+                    } else if (g_exauth_conf.exau_method == METHOD_LDAP) {
                         buf_offset += sprintf (conf_buf + buf_offset, "%s %s \"%s\" %d \"%s\" \"%s\"\n",
                                     CLI_EXAUTH_SERVER,
                                     g_exauth_conf.exauth_servers[i].id,
Index: /branches/rel_apv_10_7/usr/click/lib/libparser/commands.pm
===================================================================
--- /branches/rel_apv_10_7/usr/click/lib/libparser/commands.pm	(revision 39496)
+++ /branches/rel_apv_10_7/usr/click/lib/libparser/commands.pm	(working copy)
@@ -51112,6 +51112,18 @@
                                                         },
                                                         {
                                                                 type => "STRING",
+                                                                help_string => "Authen type (ASCII, PAP, CHAP). Default is ASCII",
+                                                                optional => "YES",
+                                                                default_value => "\"ASCII\"",
+                                                        },
+                                                        {
+                                                                type => "STRING",
+                                                                help_string => "Author service. Default is array_author",
+                                                                optional => "YES",
+                                                                default_value => "\"array_author\"",
+                                                        },
+                                                        {
+                                                                type => "STRING",
                                                                 help_string => "",
                                                                 optional => "YES",
                                                                 default_value => "\"\"",
