IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> CWMP开源代码研究4——认证流程 -> 正文阅读

[开发测试]CWMP开源代码研究4——认证流程

声明:原创作品,涉及的开源程序代码学习和研究,严禁用于商业目的。 如有任何问题,欢迎和我交流:408797506@qq.com(微信:408797506)

?

TR069 Http Digest?认证流程

一?流程及流程图

1.1盒端主动发起Http Digest认证流程?

? ? ? ? ? ?盒端CPE???????????? ?????????????????????????????ACS终端管理系统

机顶盒(CPE)通过HTTP Digest Authentication发起与终端管理系统(ACS)的认证连接,连接方式遵循RFC 2617的规定。

机顶盒连接终端管理系统的地址由Device.ManagementServer.URL参数提供。

机顶盒主动想终端管理系统发起一个HTTP 连接请求,终端管理系统会要求进行HTTP Digest Authentication认证。并按照RFC2671规范,盒端和盒端管理系统在之后的请求和应答时信息均带有认证头信息。

认证中的用户名、密码为Device.ManagementServer.Username 及Device.ManagementServer.Password

1.2???ACS主动发起Http Digest认证流程

盒端CPE??????????? ????????????????????????????ACS终端管理系统

1.<------------------http(不带auth头信息)-------------

2.------------------ 401 Unauthorized---------------->

3.<------------------http get(带auth头信息)-----------

4.------------------200 OK--------------------------->

5.<-----------------100 continue----------------------

6.------------------6 connect request---------------->

7.<------------------200 OK---------------------------

ACS终端管理系统主动发起一个HTTP 请求,CPE终端会要求进行HTTP Digest Authentication认证。并按照RFC2671规范,盒端和盒端管理系统在之后的请求和应答时信息均带有认证头信息。

认证中的用户名、密码为Device.ManagementServer.Connection.RequestUsername及Device.ManagementServer.ConnectionRequestPassword

二 详细交互流程:

2.1??盒端主动发起Http Digest认证报文?

CPE IP地址: 192.168.20.11

ACS IP地址: 192.168.20.36

1)盒端(CPE)首先发起不带认证头的Inform请求报文,内容如下:

POST /acs HTTP/1.1
Host: 192.168.20.36
Accept: */*
Connection: TE, Keep-Alive
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 3814
Expect: 100-continue
HTTP/1.1 100 Continue
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0">
??? <SOAP-ENV:Header>
??????? <cwmp:ID SOAP-ENV:mustUnderstand="1">1</cwmp:ID>
??? </SOAP-ENV:Header>
??? <SOAP-ENV:Body>
??????? <cwmp:Inform>
??????????? <DeviceId xsi:type="cwmp:DeviceIdStruct">
??????????????? <Manufacturer>Test</Manufacturer>
??????????????? <OUI>A1B2C4</OUI>
??????????????? <ProductClass>Test_PC</ProductClass>
??????????????? <SerialNumber>821281000054321</SerialNumber>
??????????? </DeviceId>
??????????? <Event SOAP-ENC:arrayType="cwmp:EventStruct[2]">
??? ????????????<EventStruct>
??????????????????? <EventCode>1 BOOT</EventCode>
??????????????????? <CommandKey></CommandKey>
??????????????? </EventStruct>
??????????????? <EventStruct>
……..

2) 盒端管理系统(ACS)收到上述报文后,发现没有认证消息(带有Authorization:标识的报文),然后发送401错误报文:

HTTP/1.1 401 Unauthorized
Date: Fri, 06 Jan 2017 02:47:12 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: JSESSIONID=12rxzt10p2rtb;Path=/
Content-Type: text/xml; charset=utf-8
WWW-Authenticate: Digest realm="XACS",qop="auth",nonce="fd171d5efcc65e79bfd8150af7f9cb21"
Content-Length: 0
Server: Jetty(6.1.20)

3 ) 盒端(cpe)收到报文后,经过分析得到报文错误为401,代码中通过分析报文中是否有WWW-Authenticate:? Digest 字段,如果具有那么通过设置函数

? //设置鉴权参数

code=curl_easy_setopt(curl,CURLOPT_HTTPAUTH,CURLAUTH_BASIC|CURLAUTH_DIGEST);

(本地配置的realm必须与收到的realm一致否则验证不能通过)将本地文件配置的realm和从盒端管理系统(ACS)收到的nonce,opaque,qop等值通过函数http_da_calc_HA1,生成一个唯一的字符串并存入response字段,并将这些信息组合到报文的头部,最后发送给ACS的报文为:

POST /acs HTTP/1.1

Authorization: Digest username="cpe",?realm=.......

POST /acs HTTP/1.1
Authorization: Digest username="cpe",?realm="XACS",?nonce="fd171d5efcc65e79bfd8150af7f9cb21", uri="/acs", cnonce="MDQ1NzA0", nc=00000001,?qop="auth", response="5f6059675ea5da97e45be615c2466ff7"
Host: 192.168.20.36
Accept: */*
Cookie: JSESSIONID=12rxzt10p2rtb
Connection: TE, Keep-Alive
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 3814
Expect: 100-continue
HTTP/1.1 100 Continue
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0">
??? <SOAP-ENV:Header>
??????? <cwmp:ID SOAP-ENV:mustUnderstand="1">1</cwmp:ID>
??? </SOAP-ENV:Header>
??? <SOAP-ENV:Body>
??????? <cwmp:Inform>
??????????? <DeviceId xsi:type="cwmp:DeviceIdStruct">
?????????????? ?<Manufacturer>Test</Manufacturer>
??????????????? <OUI>A1B2C4</OUI>
??????????????? <ProductClass>Test_PC</ProductClass>
??????????????? <SerialNumber>821281000054321</SerialNumber>
??????????? </DeviceId>
??????????? <Event SOAP-ENC:arrayType="cwmp:EventStruct[2]">
??????????????? <EventStruct>
??????????????????? <EventCode>1 BOOT</EventCode>
??????????????????? <CommandKey></CommandKey>
??????????????? </EventStruct>……….
????? …….

4)盒端管理系统(ACS)收到上述报文后,确认其含Authorization:字段,并且Authorization:字段中的response的值正确,那么认证通过,并发送回复报文:

HTTP/1.1 200 OK

HTTP/1.1 200 OK
Date: Fri, 06 Jan 2017 02:47:12 GMT
Content-Type: text/xml; charset=utf-8
Content-Length: 526
Server: Jetty(6.1.20)

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><SOAP-ENV:Header><cwmp:ID SOAP-ENV:mustUnderstand="1">1</cwmp:ID><cwmp:NoMoreRequests>0</cwmp:NoMoreRequests></SOAP-ENV:Header><SOAP-ENV:Body><cwmp:InformResponse><MaxEnvelopes>1</MaxEnvelopes></cwmp:InformResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>

5)? 盒端(CPE)收到回复报文后,分析为认证通过报文后,发送一个inform内容为空的确认报文:——其实就是个空报文

POST /acs HTTP/1.1

POST /acs HTTP/1.1
Authorization: Digest username="cpe", realm="XACS", nonce="fd171d5efcc65e79bfd8150af7f9cb21", uri="/acs", cnonce="MDQ1NzA0", nc=00000002, qop="auth", response="1b58ed5321c916998e4af9de375177fc"
    Host: 192.168.20.36
    Accept: */*
    Cookie: JSESSIONID=12rxzt10p2rtb
Connection: TE, Keep-Alive
Content-Length: 0
Content-Type: application/x-www-form-urlencoded

2.2???ACS主动发起Http Digest认证报文

略,和2.1流程类似,具体可以下载报文,自行分析。

2.3???同时开启双向认证?

即CPE终端认证ACS管理系统,和ACS管理系统认证CPE终端同时认证。成功后盒端和盒端管理系统在之后的请求和应答时信息均带有认证头信息,认证中的用户名、密码为Device.ManagementServer.Username 及Device.ManagementServer.Password

报文下载路径:

TR069HttpDigest认证流程-C文档类资源-CSDN下载

三?代码片段:

1) CPE 认证ACS管理系统的代码

//初始化curl库,设置参数用于http 传输

int http_init_curl(cwmp_context_t *cwmp_ctx, t_MemStruct *pmem, CURL **pcurl)

{

    CURLcode    code;
    CURL          *curl = NULL;
    char           *acs_usr = NULL;
    char           *acs_passwd = NULL;
    char           error_buf[CURL_ERROR_SIZE];
    CURLcode   ret = FALSE;

    if(!cwmp_ctx || !pmem || !pcurl)

    {
        CWMP_LOG_ERROR(EVENT_MODULE, "some param is NULL\n");
        return FALSE;
    }

    curl = curl_easy_init();
    if (!curl)
    {
        CWMP_LOG_ERROR(EVENT_MODULE, "curl_easy_init fail\n");
        return FALSE;
    }

    memset(error_buf, 0, sizeof(error_buf));
    code = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buf);
    if (code != CURLE_OK)

    {
        CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set error buffer [%d]\n", code);
        return FALSE;
    }

    //设置回写函数
    code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cwmp_write_func_callback);
    if (code != CURLE_OK)
    {
        CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set writer [%s]\n", curl_easy_strerror(code));
        goto finish;
    }

    code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)pmem);
    if (code != CURLE_OK)
    {
        CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set write data [%s]\n", curl_easy_strerror(code));
        goto finish;
    }

    code = curl_easy_setopt(curl, CURLOPT_COOKIEFILE,  "");
    if (code != CURLE_OK)

    {

        CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set cookie file [%s]\n", curl_easy_strerror(code));

        goto finish;

    }

    //设置鉴权参数

    code = curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC|CURLAUTH_DIGEST);
    if (code != CURLE_OK)

    {

        CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set http auth [%s]\n", curl_easy_strerror(code));

        goto finish;

    }

    get_param_value_by_fullname(IGD_ManagementServer_Username, &acs_usr);
    get_param_value_by_fullname(IGD_ManagementServer_Password, &acs_passwd);
    if (acs_usr && acs_passwd)
    {
        //curl_easy_setopt(curl, CURLOPT_USERNAME, acs_usr);
        //curl_easy_setopt(curl, CURLOPT_PASSWORD, acs_passwd);
        code = curl_easy_setopt(curl, CURLOPT_USERNAME, acs_usr);
        if (code != CURLE_OK)
        {
            CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set username [%s]\n", curl_easy_strerror(code));
            goto finish;
        }

        code = curl_easy_setopt(curl, CURLOPT_PASSWORD, acs_passwd);
        if (code != CURLE_OK)
        {
            CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set password [%s]\n", curl_easy_strerror(code));
            goto finish;
        }

        CWMP_LOG_DEBUG(EVENT_MODULE, "acs usrname=%s, passwd=%s\n", acs_usr, acs_passwd);
    }
    else
    {
        CWMP_LOG_ERROR(EVENT_MODULE, "get acs usrname or passwd fail\n");
        goto finish;
    }

    code = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);

    if (code != CURLE_OK)
    {
        CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set follow location [%s]\n", curl_easy_strerror(code));
        goto finish;
    }

    code = curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5);
    if (code != CURLE_OK)
    {
        CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set max redirs [%s]\n", curl_easy_strerror(code));
        goto finish;
    }

    code = curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
    if (code != CURLE_OK)
    {
        CWMP_LOG_ERROR(EVENT_MODULE, "Failed to set POSTREDIR [%s]\n", curl_easy_strerror(code));
        goto finish;
    }
    // http timeout 30 seconds

    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);

    // not support SSL
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);

    (*pcurl) = curl;
    ret = TRUE;
finish:
    if(ret == FALSE)
    {
        if(curl)
        {
            curl_easy_cleanup(curl);
        }
    }

    if (acs_usr)
    {
        free_check(acs_usr);
    }

    if (acs_passwd)
    {
       free_check(acs_passwd);
    }
    return ret;

}

2) CPE处理来自ACS的socket连接报文

// 处理socket连接
static void *handle_sock(void *data)
{
    Http_request    *request = NULL;
    int             sock = (int)(long)data;
    int             len = 0;
    const char      *auth_str = NULL;
    int             auth = 0;   //是否需要校验
    int             status = 0;
    char            *usrname = NULL;
    char            *passwd = NULL;
    char            resp[MAX_BUF_LEN+1] = {0};
    char            auth_opaque[33] = {0};
    CWMP_LOG_ERROR(ACS_CONN_MODULE, "handle_sock begin, sock=%d\n", sock);

    len = http_parse_request(sock, &request);

    if(len == 0)
    {
        CWMP_LOG_ERROR(ACS_CONN_MODULE, "socket:%d is closed\n", sock);
        return NULL;
    }

    if(len < 0)
    {
        CWMP_LOG_INFO(ACS_CONN_MODULE, "read data finish\n");
        goto finish;
    }

    if(!request)
    {
        CWMP_LOG_ERROR(ACS_CONN_MODULE, "http_parse_request fail\n");
        goto finish;
    }



    //判断是否需要验证

    if(g_pcwmp_ctx->dev_info.func_get_auth)
    {
        auth = g_pcwmp_ctx->dev_info.func_get_auth();
    }

    CWMP_LOG_ERROR(ACS_CONN_MODULE, "auth=%d\n", auth);

    if(auth <= 0)   //不需要校验
    {
        status = 200;
        goto response;
    }
    auth_str = http_header_get(request->header, "Authorization");

    if(!auth_str)
    {
        status = 401;
        CWMP_LOG_ERROR(ACS_CONN_MODULE, "have not Authorization\n");
        goto response;

    }

    //校验

    get_param_value_by_fullname(IGD_ManagementServer_ConnectionRequestUsername, &usrname);
    get_param_value_by_fullname(IGD_ManagementServer_ConnectionRequestPassword, &passwd);
    if(!usrname || !passwd)
    {
        status = 200;
    }

    if (check_digest_auth(auth_str, usrname, passwd) == FALSE)
    {
        status = 401;
    }

    else
    {
        status = 200;
        CWMP_LOG_INFO(ACS_CONN_MODULE, "auth pass\n");
    }

response:

    if(status == 200)
    {
        strcpy(resp, RESPONSE_200);
    }
    else if(status == 400)
    {
        strcpy(resp, RESPONSE_400);
    }
    else if(status == 401)
    {
        char buffer[256] = {0};
        char nonce[33];
        g_auth_nonce++;
        snprintf(buffer, 256,  "%d", g_auth_nonce);
        MD5(nonce, buffer, NULL);

        nonce[32] = 0;
        MD5(auth_opaque, g_auth_realm, NULL);
        snprintf(resp, MAX_BUF_LEN+1, RESPONSE_401, g_auth_realm, "auth", nonce, auth_opaque);

    }

//发送回应
    if(status != 0)
    {
        write_all(sock, resp, strlen(resp));
        CWMP_LOG_DEBUG(ACS_CONN_MODULE, "response to acs ok, status=%d\n", status);
    }

finish:
    close(sock);
    if(request)
    {
        http_destroy_request(request);
    }
    if(usrname)
    {
        free_check(usrname);
    }

    if(passwd)
    {
        free_check(passwd);
    }
    if(status == 200)
    {
        //6 Connected Request加入事件队列
        increase_event_set(EVENT_CONNECTIONREQUEST, 1);
        sem_post(&g_pcwmp_ctx->sem_send_acs);
    }
    CWMP_LOG_DEBUG(ACS_CONN_MODULE, "handle_sock end\n");
    return NULL;
}

四?总结

TR069 协议采用SSL/TLS、HTTP basic或者HTTP digest等加密认证方式可以保证数据的安全性;采用较多Web中成熟的技术,实现简单,降低了开发难度;采用HTTP协议,可以有效地穿越复杂的网络环境。因此,TR069协议比较适合对广域网内的设备进行管理。

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-01-16 13:23:15  更:2022-01-16 13:23:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 4:42:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码