折腾锐捷开机自动启动认证

学校用的是锐捷 802.1x 认证,其客户端支持开机自动启动、启动软件后自动认证。
由于我这里需要的是客户端在桌面用户没有登录系统之前就启动认证,使机器具有访问外部网络的功能。因此靠软件本身应该行不通。
想到WINDOWS系统的服务是在用户登录之前可以加载启动的,因此这里主要是把锐捷注册为服务来实现开机即认证。

首先,在锐捷客户端里设置“启动软件后自动认证”,“保存密码”等。
然后,用VC写个东东,作为服务,由它来创建锐捷认证的进程。就把生成后的程序命名为ruijie_service.exe 吧。
代码如下:
C:\\Program Files\\锐捷网络\\Ruijie Supplicant\\8021x.exe“为锐捷认证客户端的程序路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//////////////////////////////////////////////////////////////////////////////////////
//程序原作者:冷风
//修改:荒野无灯                                                             //
//////////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <tlhelp32.h>
#include <winsvc.h>


SERVICE_STATUS          ServiceStatus;
SERVICE_STATUS_HANDLE   hStatus;


VOID    WINAPI ServiceMain( DWORD dwArgc, LPTSTR *lpszArgv );
VOID    WINAPI ServiceHandler( DWORD fdwControl );
DWORD   WINAPI mainfun(LPVOID lpParam);


int main(int argc,char *argv[])
{
    SERVICE_TABLE_ENTRY ServiceTable[2];
    ServiceTable[0].lpServiceName = "8021x";
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;
    StartServiceCtrlDispatcher(ServiceTable);     // 启动服务的控制分派机线程
    return 0;
}



VOID WINAPI ServiceHandler(DWORD fdwControl)
{
    switch(fdwControl)
    {
    case SERVICE_CONTROL_PAUSE:
        ServiceStatus.dwCurrentState = SERVICE_PAUSED;
        break;

    case SERVICE_CONTROL_CONTINUE:
        ServiceStatus.dwCurrentState = SERVICE_RUNNING;
        break;

    case SERVICE_CONTROL_STOP:
    case SERVICE_CONTROL_SHUTDOWN:
        ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
        ServiceStatus.dwWin32ExitCode = 0;
        ServiceStatus.dwCheckPoint    = 0;
        ServiceStatus.dwWaitHint      = 0;
        SetServiceStatus(hStatus,&#038;ServiceStatus);
        return ;

    case SERVICE_CONTROL_INTERROGATE:
        break;

    default:
        break;
    }

    SetServiceStatus(hStatus,&#038;ServiceStatus);
    return ;
}

VOID WINAPI ServiceMain( DWORD dwArgc, LPTSTR *lpszArgv )
{
    DWORD   status = 0;
    DWORD   specificError = 0xfffffff;
 
    ServiceStatus.dwServiceType        = SERVICE_WIN32;
    ServiceStatus.dwCurrentState       = SERVICE_START_PENDING;
    ServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
    ServiceStatus.dwWin32ExitCode      = 0;
    ServiceStatus.dwServiceSpecificExitCode = 0;
    ServiceStatus.dwCheckPoint         = 0;
    ServiceStatus.dwWaitHint           = 0;
 
    hStatus = RegisterServiceCtrlHandler("8021x",(LPHANDLER_FUNCTION)ServiceHandler);
    if (hStatus==0)
        return;
 
    // Handle error condition
    status = GetLastError();
    if (status!=NO_ERROR)
    {
        ServiceStatus.dwCurrentState       = SERVICE_STOPPED;
        ServiceStatus.dwCheckPoint         = 0;
        ServiceStatus.dwWaitHint           = 0;
        ServiceStatus.dwWin32ExitCode      = status;
        ServiceStatus.dwServiceSpecificExitCode = specificError;
        SetServiceStatus(hStatus, &#038;ServiceStatus);
        return;
    }
 
    // Initialization complete - report running status
    ServiceStatus.dwCurrentState       = SERVICE_RUNNING;
    ServiceStatus.dwCheckPoint         = 0;
    ServiceStatus.dwWaitHint           = 0;  
    SetServiceStatus(hStatus, &#038;ServiceStatus);

  //do my job
   HANDLE hThread=CreateThread(NULL,0,mainfun,NULL,0,NULL);
   if(hThread==NULL)
       return;
    WaitForSingleObject(hThread,INFINITE);
}


DWORD WINAPI mainfun(LPVOID lpParam)
{


    STARTUPINFO          lpStartupInfo;
    PROCESS_INFORMATION  lpProcessInfo;

    int ret;

    GetStartupInfo(&#038;lpStartupInfo);
    lpStartupInfo.cb           = sizeof(lpStartupInfo);
    lpStartupInfo.dwFlags      = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    lpStartupInfo.wShowWindow  = SW_HIDE;
    lpStartupInfo.lpDesktop = "WinSta0\\Default";
    //lpStartupInfo.lpDesktop = "NewDesktop";

    char cmdline[MAX_PATH];
/*  char path[MAX_PATH];
    ::GetCurrentDirectory(100,path);
    strcat(path,"\\config.txt");
    FILE *fp;
    fp=fopen(path,"r");
    if(( fp=fopen(path,"r") ) !=NULL )
    {
    fread(path,MAX_PATH,1,fp);
    fclose(fp);
    strcpy(cmdline,path);
    ret = CreateProcess(cmdline, NULL, NULL,NULL,TRUE,0,NULL,NULL,&#038;lpStartupInfo,&#038;lpProcessInfo);
    }
*/

    strcpy(cmdline,"C:\\Program Files\\锐捷网络\\Ruijie Supplicant\\8021x.exe");
    ret = CreateProcess(cmdline, NULL, NULL,NULL,TRUE,0,NULL,NULL,&#038;lpStartupInfo,&#038;lpProcessInfo);
    return 0;
}

把生成的程序置于:D:\ruijie_service.exe
最后,写一个BAT脚本。内容如下:
其中D:\ruijie_service.exe 为上一步生成的程序路径。

1
2
3
4
5
6
7
@echo off
color 2f
sc create 8021x binpath= "D:\ruijie_service.exe" displayname= "8021x" depend= Tcpip
sc config 8021x start= auto
echo 设置成功
net start 8021x
pause

此脚本只需运行一遍即可。
如要删除该服务,运行如下命令即可:

1
sc delete 8021x

然后重启即可。

这样以后,只要电脑开机了,不用登录进去,机子就已经连网了。
在WIN2003 enterprise简体中文版 SP2 下测试成功。

更多
7 Responses Post a comment
  1. Junan

    :mrgreen: 在学校用VPN上网表示无压力~~

  2. 依云

    看到那些变量的前缀,半天我才明白那是什么意思——又一个微软的特性!

Leave a Reply

Note: You may use basic HTML in your comments. Your email address will not be published.

Subscribe to this comment feed via RSS