Ha1cyon_CTF-公开赛(wp)

本文深入解析了三道逆向工程题目,通过分析汇编代码和逻辑运算,揭示了加密和解密过程,最终成功破解并获取了隐藏的flag。

一.babyasm

00007FF7A8AC5A50  push        rbp  
00007FF7A8AC5A52  push        rdi  
00007FF7A8AC5A53  sub         rsp,238h  
00007FF7A8AC5A5A  lea         rbp,[rsp+20h]  
00007FF7A8AC5A5F  mov         rdi,rsp  
00007FF7A8AC5A62  mov         ecx,8Eh  
00007FF7A8AC5A67  mov         eax,0CCCCCCCCh  
00007FF7A8AC5A6C  rep stos    dword ptr [rdi]  
00007FF7A8AC5A6E  mov         rax,qword ptr [__security_cookie (07FF7A8AD3018h)]  
00007FF7A8AC5A75  xor         rax,rbp  
00007FF7A8AC5A78  mov         qword ptr [rbp+208h],rax  
00007FF7A8AC5A7F  lea         rcx,[__06A15900_ConsoleApplication@cpp (07FF7A8AD902Ah)]  
00007FF7A8AC5A86  call        __CheckForDebuggerJustMyCode (07FF7A8AC1122h)  
00007FF7A8AC5A8B  lea         rdx,[string "flag{this_is_a_fake_flag}" (07FF7A8ACF450h)]  
00007FF7A8AC5A92  lea         rcx,[flag]  
00007FF7A8AC5A96  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (07FF7A8AC15E1h)  
00007FF7A8AC5A9B  nop  
00007FF7A8AC5A9C  mov         dword ptr [p],0  
00007FF7A8AC5AA3  mov         dword ptr [rbp+64h],0  
00007FF7A8AC5AAA  jmp         main+64h (07FF7A8AC5AB4h)  
00007FF7A8AC5AAC  mov         eax,dword ptr [rbp+64h]  
00007FF7A8AC5AAF  inc         eax  
00007FF7A8AC5AB1  mov         dword ptr [rbp+64h],eax  
00007FF7A8AC5AB4  movsxd      rax,dword ptr [rbp+64h]  
00007FF7A8AC5AB8  mov         qword ptr [rbp+1F8h],rax  
00007FF7A8AC5ABF  lea         rcx,[flag]  
00007FF7A8AC5AC3  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::length (07FF7A8AC122Bh)  
00007FF7A8AC5AC8  mov         rcx,qword ptr [rbp+1F8h]  
00007FF7A8AC5ACF  cmp         rcx,rax  
00007FF7A8AC5AD2  jae         main+1B2h (07FF7A8AC5C02h)  
00007FF7A8AC5AD8  mov         eax,dword ptr [rbp+64h]  
00007FF7A8AC5ADB  and         eax,1  
00007FF7A8AC5ADE  cmp         eax,1  
00007FF7A8AC5AE1  jne         main+126h (07FF7A8AC5B76h)  
00007FF7A8AC5AE7  movsxd      rax,dword ptr [rbp+64h]  
00007FF7A8AC5AEB  mov         rdx,rax  
00007FF7A8AC5AEE  lea         rcx,[flag]  
00007FF7A8AC5AF2  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator[] (07FF7A8AC1442h)  
00007FF7A8AC5AF7  movsx       eax,byte ptr [rax]  
00007FF7A8AC5AFA  xor         eax,42h  
00007FF7A8AC5AFD  mov         dword ptr [p],eax  
00007FF7A8AC5B00  mov         dl,30h  
00007FF7A8AC5B02  lea         rcx,[rbp+144h]  
00007FF7A8AC5B09  call        std::setfill<char> (07FF7A8AC1046h)  
00007FF7A8AC5B0E  mov         qword ptr [rbp+1F8h],rax  
00007FF7A8AC5B15  mov         edx,2  
00007FF7A8AC5B1A  lea         rcx,[rbp+168h]  
00007FF7A8AC5B21  call        std::setw (07FF7A8AC10D2h)  
00007FF7A8AC5B26  mov         qword ptr [rbp+200h],rax  
00007FF7A8AC5B2D  lea         rdx,[std::hex (07FF7A8AC1488h)]  
00007FF7A8AC5B34  mov         rcx,qword ptr [__imp_std::cout (07FF7A8AD71C0h)]  
00007FF7A8AC5B3B  call        qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7160h)]  
00007FF7A8AC5B41  mov         rcx,qword ptr [rbp+200h]  
00007FF7A8AC5B48  mov         rdx,rcx  
00007FF7A8AC5B4B  mov         rcx,rax  
00007FF7A8AC5B4E  call        std::operator<<<char,std::char_traits<char>,__int64> (07FF7A8AC12F8h)  
00007FF7A8AC5B53  mov         rcx,qword ptr [rbp+1F8h]  
00007FF7A8AC5B5A  mov         rdx,rcx  
00007FF7A8AC5B5D  mov         rcx,rax  
00007FF7A8AC5B60  call        std::operator<<<char,std::char_traits<char>,char> (07FF7A8AC11A4h)  
00007FF7A8AC5B65  mov         edx,dword ptr [p]  
00007FF7A8AC5B68  mov         rcx,rax  
00007FF7A8AC5B6B  call        qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7158h)]  
00007FF7A8AC5B71  jmp         main+1ADh (07FF7A8AC5BFDh)  
00007FF7A8AC5B76  movsxd      rax,dword ptr [rbp+64h]  
00007FF7A8AC5B7A  mov         rdx,rax  
00007FF7A8AC5B7D  lea         rcx,[flag]  
00007FF7A8AC5B81  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator[] (07FF7A8AC1442h)  
00007FF7A8AC5B86  movsx       eax,byte ptr [rax]  
00007FF7A8AC5B89  mov         dword ptr [p],eax  
00007FF7A8AC5B8C  mov         dl,30h  
00007FF7A8AC5B8E  lea         rcx,[rbp+194h]  
00007FF7A8AC5B95  call        std::setfill<char> (07FF7A8AC1046h)  
00007FF7A8AC5B9A  mov         qword ptr [rbp+1F8h],rax  
00007FF7A8AC5BA1  mov         edx,2  
00007FF7A8AC5BA6  lea         rcx,[rbp+1B8h]  
00007FF7A8AC5BAD  call        std::setw (07FF7A8AC10D2h)  
00007FF7A8AC5BB2  mov         qword ptr [rbp+200h],rax  
00007FF7A8AC5BB9  lea         rdx,[std::hex (07FF7A8AC1488h)]  
00007FF7A8AC5BC0  mov         rcx,qword ptr [__imp_std::cout (07FF7A8AD71C0h)]  
00007FF7A8AC5BC7  call        qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7160h)]  
00007FF7A8AC5BCD  mov         rcx,qword ptr [rbp+200h]  
00007FF7A8AC5BD4  mov         rdx,rcx  
00007FF7A8AC5BD7  mov         rcx,rax  
00007FF7A8AC5BDA  call        std::operator<<<char,std::char_traits<char>,__int64> (07FF7A8AC12F8h)  
00007FF7A8AC5BDF  mov         rcx,qword ptr [rbp+1F8h]  
00007FF7A8AC5BE6  mov         rdx,rcx  
00007FF7A8AC5BE9  mov         rcx,rax  
00007FF7A8AC5BEC  call        std::operator<<<char,std::char_traits<char>,char> (07FF7A8AC11A4h)  
00007FF7A8AC5BF1  mov         edx,dword ptr [p]  
00007FF7A8AC5BF4  mov         rcx,rax  
00007FF7A8AC5BF7  call        qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7158h)]  
00007FF7A8AC5BFD  jmp         main+5Ch (07FF7A8AC5AACh)  
00007FF7A8AC5C02  mov         dword ptr [rbp+1E4h],0  
00007FF7A8AC5C0C  lea         rcx,[flag]  
00007FF7A8AC5C10  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > (07FF7A8AC1302h)  
00007FF7A8AC5C15  mov         eax,dword ptr [rbp+1E4h]  
00007FF7A8AC5C1B  mov         edi,eax  
00007FF7A8AC5C1D  lea         rcx,[rbp-20h]  
00007FF7A8AC5C21  lea         rdx,[__xt_z+540h (07FF7A8ACEFE0h)]  
00007FF7A8AC5C28  call        _RTC_CheckStackVars (07FF7A8AC1596h)  
00007FF7A8AC5C2D  mov         eax,edi  
00007FF7A8AC5C2F  mov         rcx,qword ptr [rbp+208h]  
00007FF7A8AC5C36  xor         rcx,rbp  
00007FF7A8AC5C39  call        __security_check_cookie (07FF7A8AC1190h)  
00007FF7A8AC5C3E  lea         rsp,[rbp+218h]  
00007FF7A8AC5C45  pop         rdi  
00007FF7A8AC5C46  pop         rbp  
00007FF7A8AC5C47  ret  

很无语,很多花指令没啥用的,给了个txt文件,应该是个加密过的,然后又给了asm文件,应该是个encoder,仔细看了看唯一动了flag的地方就是那个xor,额外关注一下,然后把加密后的转换成字符串,发现隔一个就会乱码,说明是突破点,同时发现验证后,就是偶数的时候异或,奇数不异或,写个脚本,过了

#301d7972751d6b2c6f355f3a38742d74341d61776d7d7d
str="662e61257b26301d7972751d6b2c6f355f3a38742d74341d61776d7d7d"
flag=""
w=0
for i in range(0,len(str),2):
    tmp=""
    tmp+=str[i]
    tmp+=str[i+1]
    if w%2==0:
        flag+=chr(int(tmp,16))
    else:
        a=int(tmp,16)^0x42
        flag+=chr(a)
    w+=1
# a=0x30^0x42
# print(chr(a))
print(flag)


二.Baby obfuscation

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  int v4; // ebx
  int v5; // esi
  int v6; // ebx
  int v7; // ebx
  int v8; // esi
  int v9; // edi
  int v10; // ebx
  int v11; // ebx
  int v12; // ebx
  int v13; // esi
  int v14; // eax
  int v15; // ebx
  int v16; // esi
  int v17; // ebx
  int v18; // eax
  bool v19; // bl
  int v20; // eax
  int v21; // esi
  int v22; // ebx
  int v23; // ebx
  int v24; // eax
  int v25; // eax
  int v26; // eax
  int v27; // eax
  int v28; // ebx
  int a[64]; // [rsp+20h] [rbp-60h]
  int v31; // [rsp+120h] [rbp+A0h]
  char Str[1008]; // [rsp+130h] [rbp+B0h]
  int v33[1000]; // [rsp+520h] [rbp+4A0h]
  int v34; // [rsp+14C0h] [rbp+1440h]
  int v35; // [rsp+14D0h] [rbp+1450h]
  int v36; // [rsp+14D4h] [rbp+1454h]
  int v37; // [rsp+14D8h] [rbp+1458h]
  int v38; // [rsp+14DCh] [rbp+145Ch]
  int v39; // [rsp+14E0h] [rbp+1460h]
  int v40; // [rsp+14E4h] [rbp+1464h]
  int v41; // [rsp+14E8h] [rbp+1468h]
  int v42; // [rsp+14ECh] [rbp+146Ch]
  int v43; // [rsp+14F0h] [rbp+1470h]
  int k; // [rsp+14F4h] [rbp+1474h]
  int j; // [rsp+14F8h] [rbp+1478h]
  int i; // [rsp+14FCh] [rbp+147Ch]

  _main();
  memset(v33, 0, sizeof(v33));
  v34 = 0;
  memset(a, 0, sizeof(a));
  v31 = 0;
  for ( i = 0; i <= 64; ++i )
    a[i] = i + 1;
  v39 = 2;
  v40 = 3;
  v41 = 4;
  v42 = 5;
  v35 = 2;
  v36 = 3;
  v37 = 4;
  v38 = 5;
  puts("WHERE IS MY KEY!?");
  scanf("%32s", Str);
  v43 = strlen(Str);                            // 字符串长度
  v3 = F0X1(a[j], a[j]);                        // F0x1为求最大公约数
  for ( j = v3 / a[j]; j <= v43; ++j )
  {
    v4 = (a[j] + a[j + 1]) * (a[j] + a[j + 1]);
    if ( v4 >= F0X5(2, 2) * a[j] * a[j + 1] )   // 看位数里有多少个1
    {
      v5 = ~Str[F0X4(j, 1)];                    // 减一
      v6 = F0X4(j, 1);
      v33[j] = ~(v5 + *(&v39 + v6 % F0X5(2, 2)));// F0x5是2的几次方
    }
    v7 = F0X1(a[j], a[j + 1]);
    if ( v7 > F0X1(a[j + 1], ~(~a[j + 1] + a[j])) )// 无视
    {
      v8 = v33[j];
      v9 = ~v33[j];
      v10 = F0X4(j, 1);
      v33[j] = ~(v9 + a[v10 % F0X5(2, 2)]) * v8;
    }
    v11 = a[j + 1];
    v12 = F0X5(2, 1) * v11;
    v13 = a[j];
    v14 = F0X5(2, 1);
    v15 = F0X1(v13 * v14, v12);                 // 2*a[j],2*a[j+1]
    v16 = F0X5(2, 1);
    if ( v15 == v16 * F0X1(a[j], a[j + 1]) )
    {
      v17 = F0X4(j, 1);
      v33[j] ^= *(&v39 + v17 % F0X5(2, 2));
    }
    v18 = F0X5(V0X3, a[j]);                     // 3的a[j]次方
    v19 = v18 < a[j] + 1;                       // false
    v20 = F0X5(2, 4);
    if ( F0X3(v20 >= j, v19) )                  // 无视
    {
      v21 = ~Str[F0X4(j, 1)];
      v22 = F0X4(j, 1);
      v33[j] ^= ~(v21 + *(&v39 + v22 % F0X5(2, 2)));
    }
    v23 = F0X5(2, 3);
    v24 = F0X1(a[j], a[j]);
    v33[j] *= v23 + F0X5(2, v24 / a[j]);
  }
  v25 = F0X5(2, 4);
  v26 = F0X4(v25, 1);
  if ( v26 == v43 )
  {
    v27 = F0X1(a[k], a[k]);
    for ( k = v27 / a[k]; k <= v43; ++k )
    {
      v28 = v33[k];
      if ( v28 == F0X4(A0X6[k], 1) / 10 )
        ++V0X2;
    }
    if ( V0X2 == v43 )
      puts("\nPASS");
    else
      puts("\nDENIED");
  }
  else
  {
    puts("\nDENIED");
  }
  return 0;
}
还是挺恶心人的,这么多逻辑运算,看上去挺吓人的,实际上,分析起来,发现挺简单的。。。
~ (~ a+b)这玩意的意思就是减法。。。花里胡哨。。
final=[0x0,0x1E79,0x1E79,0x2135,0x170D,0x1F41,0x1901,0x2CED,0x11F9,0x2649,0x2581,0x2DB5,0x14B5,0x25E5,0x2A31,0x30D5]
v33=[]
v39=[2,3,4,5]
v33.append(0)
for i in range(1,16):
    v33.append((final[i]-1)/10)
flag=""
for w in range(1,16):
    v33[w]/=10
    v33[w]=int(v33[w])
    v33[w]^=v39[(w-1)%4]
    v5=(~v33[w])-v39[(w-1)%4]
    flag+=chr(~v5&0xff)
print(flag)

第三题:
逻辑还是很清晰的,结果我用手逆了。。。。。。心态炸了。。。昂哥说要学会暴算,讲道理要听,
魔改了base64可还行,基本可以看出是4个字符,换成了三个字符,base64应该是3个ASCII字符,变成了4个字符。。。。直接爆破吧,手逆有点不现实,但是应该也能写出来,等wp吧,顺便学习一下

#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
__int64 __fastcall find_pos(char a1)
{
  return strrchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234{}789+/=", a1)
       - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234{}789+/=";
}
char table[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234{}789+/=";
void *__fastcall RxEncode(const char *Str, int len)
{
  void *result; // rax
  int v3; // [rsp+18h] [rbp-38h]
  signed int v4; // [rsp+1Ch] [rbp-34h]
  int v5; // [rsp+20h] [rbp-30h]
  signed int v6; // [rsp+24h] [rbp-2Ch]
  int v7; // [rsp+28h] [rbp-28h]
  int v8; // [rsp+28h] [rbp-28h]
  signed int i; // [rsp+2Ch] [rbp-24h]
  unsigned char *v10; // [rsp+30h] [rbp-20h]
  unsigned char *s; // [rsp+38h] [rbp-18h]

  v3 = 3 * (len / 4);
  v4 = 0;
  v5 = 0;
  if ( Str[len - 1] == '=' )
    v4 = 1;
  if ( Str[len - 2] == '=' )
    ++v4;
  if ( Str[len - 3] == '=' )
    ++v4;
  if ( v4 == 3 )
  {
    v3 += 2;
  }
  else if ( v4 <= 3 )
  {
    if ( v4 == 2 )
    {
      v3 += 3;
    }
    else if ( v4 <= 2 )
    {
      if ( v4 )
      {
        if ( v4 == 1 )
          v3 += 4;
      }
      else
      {
        v3 += 4;
      }
    }
  }
  s =(unsigned char*)malloc(v3);
  if ( s )
  {
    memset(s, 0, v3);
    v10 = s;
    while ( v5 < len - v4 )
    {
      v6 = 0;
      v7 = 0;
      while ( v6 <= 3 && v5 < len - v4 )
      {
        v7 = (v7 << 6) | (char)find_pos(Str[v5]);
        ++v6;
        ++v5;
      }
      v8 = v7 << 6 * (4 - v6);
      for ( i = 0; i <= 2 && i != v6; ++i )
        *v10++ = v8 >> 8 * (2 - i);
    }
    *v10 = 0;
    result = s;
  }
  else
  {
    puts("No enough memory.");
    result = 0LL;
  }
  return result;
}
void Solve(int a,int b,int c,int trys)
{
	for(int i=0;i<strlen(table);i++)
		for(int j=0;j<strlen(table);j++)
			for(int k=0;k<strlen(table);k++)
				for(int l=0;l<strlen(table);l++)
				{
					char test[4];
					test[0]=table[i];
					test[1]=table[j];
					test[2]=table[k];
					test[3]=table[l];
					test[4]='\0';
					unsigned char *str=(unsigned char *)RxEncode(test,4);
					if(str[0]==a && str[1]==b && str[2]==c)
					{
						printf("%c%c%c%c  %d\n",table[i],table[j],table[k],table[l],trys);
					}
						
				}
}//npuctf{w0w+y0U+cAn+r3lllY+dAnc3}
int main()
{
	int data[25]={0x9E,0x9B,0x9C,0xB5,0xFE,0x70,0xD3,0x0F,0xB2,0xD1,0x4F,0x9C,0x02,0x7F,0xAB,0xDE,0x59,0x65,0x63,0xE7,0x40,0x9D,0xCD,0xFA};
	for(int i=0;i<8;i++)
		Solve(data[3*i],data[3*i+1],data[3*i+2],i);
    return 0;
}

name: deepsatmodels channels: - conda-forge - defaults dependencies: - _libgcc_mutex=0.1=main - blas=1.0=mkl - ca-certificates=2020.7.22=0 - certifi=2020.6.20=py38_0 - cloudpickle=1.5.0=py_0 - cudatoolkit=10.1.243=h6bb024c_0 - cycler=0.10.0=py_2 - cython=0.29.21=py38h950e882_0 - cytoolz=0.10.1=py38h516909a_0 - dask-core=2.21.0=py_0 - decorator=4.4.2=py_0 - enum34=1.1.10=py38h32f6830_1 - freetype=2.10.2=h5ab3b9f_0 - imagecodecs-lite=2019.12.3=py38h8790de6_1 - imageio=2.9.0=py_0 - intel-openmp=2020.1=217 - joblib=0.16.0=py_0 - jpeg=9b=h024ee3a_2 - kiwisolver=1.2.0=py38hbf85e49_0 - lcms2=2.11=h396b838_0 - ld_impl_linux-64=2.33.1=h53a641e_7 - libedit=3.1.20191231=h14c3975_1 - libffi=3.3=he6710b0_2 - libgcc-ng=9.1.0=hdf63c60_0 - libgfortran-ng=7.3.0=hdf63c60_0 - libpng=1.6.37=hbc83047_0 - libstdcxx-ng=9.1.0=hdf63c60_0 - libtiff=4.1.0=h2733197_1 - lz4-c=1.9.2=he6710b0_0 - matplotlib=3.3.0=1 - matplotlib-base=3.3.0=py38h91b0d89_1 - mkl=2020.1=217 - mkl-service=2.3.0=py38he904b0f_0 - mkl_fft=1.1.0=py38h23d657b_0 - mkl_random=1.1.1=py38h0573a6f_0 - ncurses=6.2=he6710b0_1 - networkx=2.4=py_1 - ninja=1.9.0=py38hfd86e86_0 - numpy=1.18.5=py38ha1c710e_0 - numpy-base=1.18.5=py38hde5b4d6_0 - olefile=0.46=py_0 - openssl=1.1.1g=h516909a_1 - pandas=1.0.5=py38h0573a6f_0 - pathlib=1.0.1=py38h32f6830_2 - pillow=7.2.0=py38hb39fc2d_0 - pip=20.1.1=py38_1 - pycocotools=2.0.1=py38h1e0a361_1 - pyparsing=2.4.7=pyh9f0ad1d_0 - python=3.8.3=hcff3b4d_2 - python-dateutil=2.8.1=py_0 - python_abi=3.8=1_cp38 - pytz=2020.1=py_0 - pywavelets=1.1.1=py38h8790de6_1 - pyyaml=5.3.1=py38h1e0a361_0 - readline=8.0=h7b6447c_0 - scikit-image=0.17.2=py38hcb8c335_1 - scikit-learn=0.23.1=py38h423224d_0 - setuptools=49.2.0=py38_0 - six=1.15.0=py_0 - sqlite=3.32.3=h62c20be_0 - threadpoolctl=2.1.0=pyh5ca1d4c_0 - tifffile=2019.7.26.2=py38_0 - tk=8.6.10=hbc83047_0 - toolz=0.10.0=py_0 -应该怎么改
03-16
#include "rtspserver.h" //#include "libctaocrypt/base64.h" #include "sslApi.h" #include "auth/authentication.h" #include "rtsp_server_module.h" #include "datasrc/data_src.h" #include "rtspsession/rtp4server.h" extern pthread_mutex_t g_rtsp_mutex; static int TPRtspSocketInit(TPRTSPSERVER *pRtspServer); static int TPRtspClose(TPRTSPSERVER *pRtspServer); static int TPRtspCloseClientSocket(TPRTSPSERVER *pRtspServer, int iClientSocket); int TPRtspInit(TPRTSPSERVER *pRtspServer, int iServerPort, int bNonblockSock) { int i; RETURN_IVALID_IF(!pRtspServer) pRtspServer->bNonblock = bNonblockSock; pRtspServer->bIsRunning = 0; pRtspServer->iNumClients = 0; pRtspServer->iPlaybackNum = 0; pRtspServer->pArgs = NULL; pRtspServer->pOnAcceptSucceededCallback = NULL; pRtspServer->iSock = -1; for (i = 0; i < TP_TCP_MAX_CLIENT; i++) { pRtspServer->pClients[i] = NULL; } memset(&pRtspServer->ServerAddr, 0, sizeof(struct sockaddr_in)); pRtspServer->ServerAddr.sin_family = AF_INET; #ifdef SRTP_SUPPORT if (iServerPort == SRTP_DEFAULT_PORT) { pRtspServer->ServerAddr.sin_addr.s_addr = inet_addr(LOCAL_IP_ADDR); } else #endif { pRtspServer->ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY); } pRtspServer->ServerAddr.sin_port = htons(iServerPort); pRtspServer->iPort = iServerPort; pRtspServer->bIsReadytoAccept = 1; TPRtspUpdateServerIP(pRtspServer); pRtspServer->iNeedAuthentication = 0; pRtspServer->media_encrypt = 0; pRtspServer->rtspAuthManeger = (AUTHMANAGER *)malloc(sizeof(AUTHMANAGER)); if (pRtspServer->rtspAuthManeger == NULL) { RTSP_ERROR("no memory!"); return -1; } initAuthManager(pRtspServer->rtspAuthManeger, 10, 1800); pRtspServer->iUserNum = 0; #ifdef VIDEO_AVBR_ENABLE pRtspServer->bIsVirtualIFrameEnabled = 1; #else pRtspServer->bIsVirtualIFrameEnabled = 0; #endif return 0; } int TPRtspDeInit(TPRTSPSERVER *pRtspServer) { int i = 0; int trytimes =1000; RETURN_IVALID_IF(!pRtspServer) for (i = 0; i < TPRTSPSERVER_MAX_SESSION; i++) { pthread_mutex_lock(&g_rtsp_mutex); if (pRtspServer->pClients[i] != NULL) { //TPRtspCloseSession(pRtspServer, i); pRtspServer->pClients[i]->iStatus = SESSION_STOPPING; } pthread_mutex_unlock(&g_rtsp_mutex); } while(pRtspServer->iNumClients > 0 && trytimes > 0) { usleep(1000); trytimes--; } if (pRtspServer->bIsRunning == 1) { TPRtspStop(pRtspServer); } DeinitAuthManager(pRtspServer->rtspAuthManeger); free(pRtspServer->rtspAuthManeger); if (pRtspServer->iSock >= 0) { TPRtspClose(pRtspServer); } return 0; } static int TPRtspSocketInit(TPRTSPSERVER *pRtspServer) { int on = 1; /* 忽略client网络异常断开所产生的SIGPIPE信号 */ signal(SIGPIPE, SIG_IGN); if ((pRtspServer->iSock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { RTSP_ERROR("socket create failed."); return TP_TCP_EC_FAILURE; } //允许地址重复绑定 setsockopt(pRtspServer->iSock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); ioctl(pRtspServer->iSock, FIONBIO, &pRtspServer->bNonblock); if (bind(pRtspServer->iSock, (struct sockaddr *)&pRtspServer->ServerAddr, sizeof(pRtspServer->ServerAddr))) { RTSP_ERROR("socket bind failed."); TPRtspClose(pRtspServer); return TP_TCP_EC_FAILURE; } /* 监听 */ if (listen(pRtspServer->iSock, TP_TCP_MAX_CLIENT)) { RTSP_ERROR("socket listen failed."); TPRtspClose(pRtspServer); return TP_TCP_EC_FAILURE; } return TP_TCP_EC_OK; } static int TPRtspClose(TPRTSPSERVER *pRtspServer) { if(pRtspServer->iSock > 0) { close(pRtspServer->iSock); pRtspServer->iSock = -1; } return TP_TCP_EC_OK; } static int TPRtspCloseClientSocket(TPRTSPSERVER *pRtspServer, int iClientSocket) { if (iClientSocket >= 0) { close(iClientSocket); } return TP_TCP_EC_OK; } static void RtspPutUshortToBufBE(unsigned char * buf, unsigned short value) { buf[0] = (value >> 8) & 0xff; buf[1] = value & 0xff; } static void RtspPutUintToBufBE(unsigned char * buf, unsigned int value) { buf[0] = (value >> 24) & 0xff; buf[1] = (value >> 16) & 0xff; buf[2] = (value >> 8) & 0xff; buf[3] = value & 0xff; } void RtspGetUshortFromBufBE(unsigned char * buf, unsigned short *value) { if (buf && value) { *value = (buf[0] << 8) | buf[1]; } } void RtspGetUintFromBufBE(unsigned char * buf, unsigned int *value) { if (buf && value) { *value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; } } int RtspAddExtention(unsigned char * buf, unsigned long long utctime, unsigned char flag) { int ret = RTP_EXTEN_HEADER_LEN; RtspPutUshortToBufBE(buf, RTP_EXTEN_VERSION); /*帧标记*/ buf[ret] = RTP_EXTEN_TYPE_FRAME; RtspPutUshortToBufBE(buf + ret + 1, RTP_EXTEN_FRAM_LEN); buf[ret + RTP_EXTEN_TYPE_HEADER_LEN] = flag; ret += RTP_EXTEN_TYPE_HEADER_LEN + RTP_EXTEN_FRAM_LEN; /*utc时间*/ if(utctime != 0) { unsigned int time_sec = (unsigned int)(utctime / 1000000); buf[ret] = RTP_EXTEN_TYPE_UTC; RtspPutUshortToBufBE(buf + ret + 1, RTP_EXTEN_UTC_LEN); buf[ret + RTP_EXTEN_TYPE_HEADER_LEN] = 0x00; RtspPutUintToBufBE(buf + ret + RTP_EXTEN_LEN_EQUAL_BITS, time_sec); ret += RTP_EXTEN_TYPE_HEADER_LEN + RTP_EXTEN_UTC_LEN; } RtspPutUshortToBufBE(buf + 2, (unsigned short)ret / RTP_EXTEN_LEN_EQUAL_BITS - 1); return ret; } int RtspAddAvbrExtention(unsigned char * buf) { int ret = RTP_EXTEN_HEADER_LEN; RtspPutUshortToBufBE(buf, RTP_RTSP_EXTEN_VERSION); /*帧标记*/ RtspPutUintToBufBE(buf + ret, RTP_RTSP_VIRTUAL_I_FRAME_VALUE); ret += RTP_RTSP_VIRTUAL_I_FRAME_LEN; RtspPutUshortToBufBE(buf + 2, (unsigned short)ret / RTP_EXTEN_LEN_EQUAL_BITS - 1); return ret; } int rtp_set_retry_info(trans_session_desc_t *desc, trans_stream_t *stream) { TPRTSPSERVERSESSION *session = NULL; TPRTPPACKAGE *ptr_rtp_package = NULL; int tmp = 0; RETRY_INFO *p_retry_info = NULL; RETURN_VALUE_IF(!desc || !stream || !stream->package, ERROR); session = (TPRTSPSERVERSESSION *)desc->priv; ptr_rtp_package = (TPRTPPACKAGE *)stream->package; if (ptr_rtp_package->stream_type == RTP_SESSION_AUDIO) { p_retry_info = &session->audio_retry_info; } else { p_retry_info = &session->video_retry_info; } ptr_rtp_package->stash_sn = ptr_rtp_package->PayloadContext.RTPHeader.usSequenceNumber; ptr_rtp_package->PayloadContext.RTPHeader.usSequenceNumber = p_retry_info->sn; ptr_rtp_package->PayloadContext.cur_nalu_index = p_retry_info->nalu_index; ptr_rtp_package->pESBuffer->iIndexHead = 0; tmp = p_retry_info->nalu_index; while (tmp > 0) { MBUFFERESAdvanceFrame(ptr_rtp_package->pESBuffer); tmp--; } rtp_pack_init_payload_context(ptr_rtp_package); ptr_rtp_package->PayloadContext.bPayloadInited = p_retry_info->payload_init; ptr_rtp_package->PayloadContext.iCurPayloadPos = p_retry_info->payload_pos; ptr_rtp_package->PayloadContext.bSbit = p_retry_info->b_sbit; return OK; } int rtp_recover_retry_info(trans_stream_t * stream) { RETURN_VALUE_IF(!stream || !stream->package, ERROR); TPRTPPACKAGE * ptr_rtp_package = (TPRTPPACKAGE *)stream->package; ptr_rtp_package->PayloadContext.RTPHeader.usSequenceNumber = ptr_rtp_package->stash_sn; return OK; } static void set_retry_info(RETRY_INFO *retry_info, TPRTPPACKAGE *rtp_pack, S32 rtp_len) { /* rtp包构建之后,sn会自增1,要保留现场要将当前的sn - 1 */ retry_info->sn = rtp_pack->PayloadContext.RTPHeader.usSequenceNumber - 1; retry_info->nalu_index = rtp_pack->PayloadContext.sending_nalu_index; /* payload回退到打包RTP之前的位置 */ retry_info->payload_pos = rtp_pack->PayloadContext.iCurPayloadPos - rtp_len; retry_info->payload_init = 1; retry_info->b_sbit = rtp_pack->PayloadContext.last_bSbit; retry_info->retry_flag = 1; } static void reset_retry_info(RETRY_INFO *retry_info, TPRTPPACKAGE *rtp_pack) { RETURN_VOID_IF(!retry_info || !rtp_pack); retry_info->send_pos = 0; retry_info->sn = rtp_pack->PayloadContext.RTPHeader.usSequenceNumber; retry_info->payload_init = 0; retry_info->nalu_index = 0; retry_info->b_sbit = 0; retry_info->retry_flag = 0; retry_info->payload_pos = 0; } int rtp_clear_retry_info(trans_session_desc_t *desc, trans_stream_t * stream) { RETURN_VALUE_IF(!desc || !stream || !stream->package, ERROR); TPRTPPACKAGE *ptr_rtp_package = (TPRTPPACKAGE *)stream->package; TPRTSPSERVERSESSION *pSession = (TPRTSPSERVERSESSION *)desc->priv; RETRY_INFO *p_retry_info = &pSession->video_retry_info; reset_retry_info(p_retry_info, ptr_rtp_package); return OK; } int rtp_get_package_sn(trans_session_desc_t *desc, trans_stream_t * stream) { RETURN_VALUE_IF(!stream || !stream->package, ERROR); TPRTPPACKAGE *ptr_rtp_package = (TPRTPPACKAGE *)stream->package; return ptr_rtp_package->PayloadContext.RTPHeader.usSequenceNumber; } int rtp_set_retry_sn(trans_session_desc_t *desc, trans_stream_t * stream, int seq) { RETURN_VALUE_IF(!desc || !desc->priv || !stream || !stream->package, ERROR); TPRTPPACKAGE *ptr_rtp_package = (TPRTPPACKAGE *)stream->package; TPRTSPSERVERSESSION *pSession = (TPRTSPSERVERSESSION *)desc->priv; RETRY_INFO *p_retry_info = &pSession->video_retry_info; reset_retry_info(p_retry_info, ptr_rtp_package); p_retry_info->sn = seq; return OK; } #ifdef RTP_RETANS_SUPPORT static int save_rtppackge_2_retrans_queue(TPRTP4SERVER *pserver, int session, MBUFFERByteArray *pByteArray, int is_iframe) { if (session != RTP_SESSION_VIDEO) { return OK; } RETURN_IVALID_IF(!pserver || !pByteArray || !pserver->pSessions[session]); if (pserver->bRTPOverTCP || !pserver->pSessions[session]->retrans_enable) { return OK; } int rtplen = MBUFFERByteArrayLength(pByteArray); int max_size = 0; TPRTPSESSIONCONTEXT* psession = pserver->pSessions[session]; int pos = psession->qindex & psession->winmask; int pre_pos = (psession->qindex - 1) & psession->winmask; BOOL frame_type_changed = FALSE; max_size = MAX_TRANS_BUF_SIZE; if (rtplen > max_size) { RTSP_ERROR("RTP:rtp size exceed max buf size, max_size = %d!", max_size); return ERROR; } RE_TRANS_NODE ** pqueue = psession->re_trans_queue; frame_type_changed = ((is_iframe == (pqueue[pre_pos]->is_key_frame)) ? FALSE : TRUE); if (!pqueue[pos]->buf) { pqueue[pos]->buf = malloc(max_size); if (!pqueue[pos]->buf) { RTSP_ERROR("malloc memory failed!"); return ERROR; } memset(pqueue[pos]->buf, 0x0, max_size); } else { reset_rtp_retrans_node(pqueue[pos]); } if (is_iframe) { if (frame_type_changed) { psession->temp_key_frame_count = 0; } pqueue[pos]->is_key_frame = TRUE; psession->temp_key_frame_count++; } else { if (frame_type_changed) { psession->latest_key_frame_qindex = psession->qindex - psession->temp_key_frame_count; psession->latest_key_frame_count = psession->temp_key_frame_count; RTSP_DEBUG("RTP:latest_key_frame_qindex = %d, count = %d!", psession->latest_key_frame_qindex, psession->latest_key_frame_count); } } memcpy(pqueue[pos]->buf, pByteArray->pucBuffer, rtplen); pqueue[pos]->len = rtplen; pqueue[pos]->send_time = RTSPGetTimeMS(); psession->qindex++; return OK; } #endif /* 自1900到1970的秒数 由于time获取的是1970到当前时间的时差 而rtcp协议中规定的时间是从1900年开始 */ #define TIME_OFFSET ((70LL * 365 + 17) * 24 * 60 * 60) #define TEMP_FORMAT_LEN 8 int TPSendRtpQueueCb(trans_session_desc_t *desc, trans_stream_t *stream) { RTPDATAFRAME *p_frame = NULL; TPRTSPSERVERSESSION *pSession = NULL; TPRTPPACKAGE *ptr_rtp_package = NULL; int iSessionID = 0; int sendmute = 0; unsigned char mutebuf[RTP_MAX_PACKET_SIZE] = {0}; unsigned char RTPextern[RTP_MAX_EXTEN_LEN + 1] = {0}; unsigned char pucPrefix[RTP_PREFIX_SIZE] = {0}; int externtionlen = 0; unsigned long cur_time = 0; struct iovec iov[RTP_MAX_SEND_NUM * 2]; int ret = 0; RETRY_INFO *p_retry_info = NULL; RETRY_INFO tmp_retry_info = {0}; int iSize = 0; BOOL bSendRTCP = TRUE; TPRTPSESSIONCONTEXT * ptprtpsessioncontext = NULL; unsigned long rtp_timestamp = 0; unsigned long long ullTimeSent = 0; unsigned int uSSRC; int send_freq = 0; struct timespec CurTimeSpec = {0, 0}; #if (defined SRTP_SUPPORT) || (defined SRTP_ENCRYPT_WITH_KEY_NEGOTIATION) unsigned char tmpbuf[RTP_MAX_PACKET_SIZE] = {0}; #endif RETURN_VALUE_IF(!desc || !desc->send_data || !desc->priv || !stream->package, 0); p_frame = (RTPDATAFRAME *)desc->send_data; pSession = (TPRTSPSERVERSESSION *)desc->priv; ptr_rtp_package = (TPRTPPACKAGE *)stream->package; /* 可能底层给的数据是错的,这里就可能出现打包异常,增加一个防护机制 */ RETURN_VALUE_IF(!p_frame->rtp_head_pos || !p_frame->rtp_payload_pos, 0); if(pSession->pRTPServer->bIsRunning != 1) { return 0; } if ( ptr_rtp_package->av_codec >= TP_ENCODE_TYPE_AUDIO_MIN && ptr_rtp_package->av_codec <= TP_ENCODE_TYPE_AUDIO_MAX) { iSessionID = RTP_SESSION_AUDIO; } #ifdef RTSP_USE_SMART_DATA else if (TP_ENCODE_TYPE_VIDEO_SMART == ptr_rtp_package->av_codec) { iSessionID = RTP_SESSION_SMART_DATA; } #endif else if (TP_ENCODE_TYPE_VIDEO_SMART != ptr_rtp_package->av_codec) { iSessionID = RTP_SESSION_VIDEO; } p_retry_info = (iSessionID == RTP_SESSION_AUDIO) ? &pSession->audio_retry_info : &pSession->video_retry_info; if (iSessionID != RTP_SESSION_AUDIO && iSessionID != RTP_SESSION_VIDEO) { p_retry_info = &tmp_retry_info; } //没收到I帧数据的话其他的数据丢掉 #ifdef JPEG_STREAM_ENABLE if ((!pSession->getIFrame && (!ptr_rtp_package->is_iframe || !ptr_rtp_package->is_first_rtp || p_retry_info->retry_flag)) && pSession->iStreamType != TPRTP_STREAM_TYPE_VIDEO_JPEG) #else if (!pSession->getIFrame && (!ptr_rtp_package->is_iframe || !ptr_rtp_package->is_first_rtp || p_retry_info->retry_flag)) #endif { p_retry_info->send_pos = 0; p_retry_info->retry_flag = 0; return 0; } #if (defined SRTP_SUPPORT) || (defined SRTP_ENCRYPT_WITH_KEY_NEGOTIATION) if ((strcmp(pSession->pcClientIP, "127.0.0.1") == 0 #ifdef SRTP_ENCRYPT_WITH_KEY_NEGOTIATION || pSession->pRTPServer->srtp #endif ) && iSessionID == RTP_SESSION_VIDEO && p_frame->rtp_head_len == 12 && (*(p_frame->rtp_payload_pos) & 0x1f) == 0x06) { return 0; } #endif if (!pSession->getIFrame && pSession->ulFirstVideoRTPTS == 0) { pSession->ulFirstVideoRTPTS = (unsigned long)ptr_rtp_package->curPTS; } else if (pSession->getIFrame && pSession->ulFirstAudioRTPTS == 0 && iSessionID == RTP_SESSION_AUDIO) { pSession->ulFirstAudioRTPTS = (unsigned long)ptr_rtp_package->curPTS; } #ifdef RTSP_USE_SMART_DATA else if (pSession->getIFrame && pSession->ulFirstSmartRTPTS == 0 && iSessionID == RTP_SESSION_SMART_DATA) { pSession->ulFirstSmartRTPTS = (unsigned long)ptr_rtp_package->curPTS; } #endif pSession->getIFrame = 1; /* 如果音频或视频流没有传输完,则不能交叉传输,需要将剩余数据发完,其他流走重传流程 */ if ((pSession->video_retry_info.send_pos != 0 && iSessionID != RTP_SESSION_VIDEO) || (pSession->audio_retry_info.send_pos != 0 && iSessionID != RTP_SESSION_AUDIO)) { set_retry_info(p_retry_info, ptr_rtp_package, p_frame->rtp_payload_len); return RTSP_SEND_RETRY; } if (ptr_rtp_package->av_codec != TP_ENCODE_TYPE_UNDET && iSessionID == RTP_SESSION_VIDEO) { char codestr[TEMP_FORMAT_LEN]; if (ptr_rtp_package->av_codec == TP_ENCODE_TYPE_VIDEO_H264) snprintf(codestr, TEMP_FORMAT_LEN, "H264"); else if (ptr_rtp_package->av_codec == TP_ENCODE_TYPE_VIDEO_H265) snprintf(codestr, TEMP_FORMAT_LEN, "H265"); #ifdef JPEG_STREAM_ENABLE else if (ptr_rtp_package->av_codec == TP_ENCODE_TYPE_SNAPSHOT_JPEG) snprintf(codestr, TEMP_FORMAT_LEN, "JPEG"); #endif else return 0; if (strcmp(pSession->SDPServer.SDPInfo.MediaInfo.pcVideoFormat, codestr) != 0) { snprintf(pSession->SDPServer.SDPInfo.MediaInfo.pcVideoFormat, 16, codestr); } } if(RTP4SIsMulticast(pSession->pRTPServer) && p_frame->multicast_send == 1) { return 0; } else if(RTP4SIsMulticast(pSession->pRTPServer)) { p_frame->multicast_send = 1; } #ifdef RTCP_PSFB_SUPPORT if (pSession->pRTPServer->pSessions[ptr_rtp_package->stream_type]) { pSession->pRTPServer->pSessions[ptr_rtp_package->stream_type]->psfb_control.is_iframe = ptr_rtp_package->is_iframe; } #endif RtspPutUintToBufBE((unsigned char *)p_frame->rtp_head_pos + 8, pSession->pRTPServer->pSessions[iSessionID]->iClientSSRC); RtspGetUintFromBufBE((unsigned char *)p_frame->rtp_head_pos + 4, (unsigned int *)&cur_time); rtp_timestamp = cur_time - ((iSessionID == RTP_SESSION_VIDEO) ? pSession->ulFirstVideoRTPTS : pSession->ulFirstAudioRTPTS); RtspPutUintToBufBE((unsigned char *)p_frame->rtp_head_pos + 4,rtp_timestamp); #if (defined SRTP_SUPPORT) || (defined SRTP_ENCRYPT_WITH_KEY_NEGOTIATION) if(strcmp(pSession->pcClientIP, "127.0.0.1") == 0 #ifdef SRTP_ENCRYPT_WITH_KEY_NEGOTIATION || pSession->pRTPServer->srtp #endif ) { RtspPutUshortToBufBE((unsigned char *)p_frame->rtp_head_pos + 2, pSession->pRTPServer->pSessions[iSessionID]->seq_no); } else #endif { RtspPutUshortToBufBE((unsigned char *)p_frame->rtp_head_pos + 2, pSession->pRTPServer->pSessions[iSessionID]->rtp_seq); } #ifdef RTSP_USE_SMART_DATA if (RTP_SESSION_SMART_DATA == iSessionID) { RtspPutUintToBufBE((unsigned char *)p_frame->rtp_head_pos + 4, cur_time - pSession->ulFirstSmartRTPTS ); } #endif /* TP NVR虚拟I帧的RTP包要包含扩展字段 */ if (pSession->bIsVirtualIFrameEnabled && ptr_rtp_package->is_virtual_iframe == 1) { *(p_frame->rtp_head_pos) |= RTP_HEADER_EXTENTION_BIT; externtionlen = RtspAddAvbrExtention(RTPextern); } iSize = RTPDataGetFrameSize(p_frame); if(pSession->bRTPOverTCP) { int rtp_length = p_frame->rtp_head_len + p_frame->rtp_payload_len + externtionlen; int send_count = 0; int expectlen = 0; int rtp_cur_index = pSession->rtp_send_data_index; int i = 0; pucPrefix[0] = '$'; pucPrefix[1] = pSession->piTCPDataID[iSessionID]; pucPrefix[2] = rtp_length >> 8; pucPrefix[3] = rtp_length & 0xff; #ifdef SRTP_ENCRYPT_WITH_KEY_NEGOTIATION MBUFFERByteArray mBuffer; unsigned char TXBufferMemSpace[TPRTSPSERVER_BUFFER_SIZE] = {0}; MBUFFERByteArrayInit(TXBufferMemSpace, 0, 0, TPRTSPSERVER_BUFFER_SIZE - 4, &mBuffer); MBUFFERByteArrayReset(&mBuffer); if (pSession->pRTPServer->srtp) { struct srtp_session *enc_sess = &pSession->pRTPServer->pSessions[iSessionID]->encrypt_session; unsigned int roc = htonl(pSession->pRTPServer->pSessions[iSessionID]->roc_send); unsigned int ssrc = htonl(pSession->pRTPServer->pSessions[iSessionID]->iClientSSRC); unsigned int iv[] = {0x00, ssrc, roc, htonl((pSession->pRTPServer->pSessions[iSessionID]->seq_no) << 16)}; int rtp_payload_len = 0; /* 将等效payload添加进tmpbuf待加密,RTP头部放入mBbuffer*/ if (p_frame->rtp_head_len == 14) /* 暂不知何时头长度为14字节 */ { memcpy(tmpbuf, p_frame->rtp_head_pos + 12, 2); memcpy(tmpbuf + 2, p_frame->rtp_payload_pos, p_frame->rtp_payload_len); rtp_payload_len = 2 + p_frame->rtp_payload_len; MBUFFERByteArrayPutMultiUCharBE((unsigned char *)p_frame->rtp_head_pos, 12, &mBuffer); } else { memcpy(tmpbuf, p_frame->rtp_payload_pos, p_frame->rtp_payload_len); rtp_payload_len = p_frame->rtp_payload_len; MBUFFERByteArrayPutMultiUCharBE((unsigned char *)p_frame->rtp_head_pos, p_frame->rtp_head_len, &mBuffer); } /* payload加密 */ tpsocket_aes_cm_encrypt((unsigned char *)tmpbuf, (unsigned char *)tmpbuf, rtp_payload_len, &enc_sess->aes_key, (unsigned char *)enc_sess->rtp_salt, (unsigned char *)&iv); MBUFFERByteArrayPutMultiUCharBE((unsigned char *)tmpbuf, rtp_payload_len, &mBuffer); /* rtp头与加密payload一起做hash计算 */ if (enc_sess->auth_len) { char hash[20]; struct tpsocket_sha sha; memcpy(&sha, &enc_sess->sha, sizeof(sha)); tpsocket_sha_update(&sha, mBuffer.pucBuffer, mBuffer.iCurPos); tpsocket_sha_update(&sha, &roc, sizeof(roc)); tpsocket_sha_final(&sha, (unsigned char *)hash); tpsocket_sha_init(&sha); tpsocket_sha_update(&sha, enc_sess->sha_opad, sizeof(enc_sess->sha_opad)); tpsocket_sha_update(&sha, hash, sizeof(hash)); tpsocket_sha_final(&sha, (unsigned char *)hash); MBUFFERByteArrayPutMultiUCharBE((unsigned char *)hash, enc_sess->auth_len, &mBuffer); // 20 bytes in total, low 10 bytes picked only } /* 修改RTSP头部包len说明(增加hash长度) */ rtp_length += enc_sess->auth_len; // 10 bytes hash pucPrefix[2] = rtp_length >> 8; pucPrefix[3] = rtp_length & 0xff; } #endif iov[send_count].iov_base = pucPrefix; iov[send_count++].iov_len = 4; #ifdef SRTP_ENCRYPT_WITH_KEY_NEGOTIATION if (pSession->pRTPServer->srtp) { iov[send_count].iov_base = mBuffer.pucBuffer; iov[send_count++].iov_len = p_frame->rtp_head_len; } else #endif { if (externtionlen > 0) { int fu_header_len = p_frame->rtp_head_len - RTP_HEADER_SIZE; iov[send_count].iov_base = p_frame->rtp_head_pos; iov[send_count++].iov_len = RTP_HEADER_SIZE; iov[send_count].iov_base = RTPextern; iov[send_count++].iov_len = externtionlen; if(fu_header_len > 0) { iov[send_count].iov_base = p_frame->rtp_head_pos + RTP_HEADER_SIZE; iov[send_count++].iov_len = fu_header_len; } } else { iov[send_count].iov_base = p_frame->rtp_head_pos; iov[send_count++].iov_len = p_frame->rtp_head_len; } } iov[send_count].iov_base = sendmute ? mutebuf : p_frame->rtp_payload_pos; iov[send_count++].iov_len = p_frame->rtp_payload_len; pSession->rtp_send_data[rtp_cur_index].rtp_head_size = 0; for (i = 0; i < send_count - 1; i ++) { memcpy(pSession->rtp_send_data[rtp_cur_index].rtp_header_data + pSession->rtp_send_data[rtp_cur_index].rtp_head_size, iov[i].iov_base, iov[i].iov_len); pSession->rtp_send_data[rtp_cur_index].rtp_head_size += iov[i].iov_len; } #ifdef SRTP_ENCRYPT_WITH_KEY_NEGOTIATION /* 包数据存入rtp_send_data */ if (pSession->pRTPServer->srtp) { if(NULL == pSession->rtp_send_data[rtp_cur_index].rtp_playload_pos || 0 == pSession->rtp_send_data[rtp_cur_index].rtp_playload_size) pSession->rtp_send_data[rtp_cur_index].rtp_playload_pos = (unsigned char *)malloc(RTP_MAX_PACKET_SIZE + 100); memcpy(pSession->rtp_send_data[rtp_cur_index].rtp_playload_pos, mBuffer.pucBuffer + p_frame->rtp_head_len, mBuffer.iCurPos - p_frame->rtp_head_len); pSession->rtp_send_data[rtp_cur_index].rtp_playload_size = mBuffer.iCurPos - p_frame->rtp_head_len; } else #endif { pSession->rtp_send_data[rtp_cur_index].rtp_playload_pos = iov[i].iov_base; pSession->rtp_send_data[rtp_cur_index].rtp_playload_size = iov[i].iov_len; } pSession->rtp_send_data_index++; /*还原设置的拓展标记,避免对其他会话的影响*/ if(*(p_frame->rtp_head_pos) & RTP_HEADER_EXTENTION_BIT) { *(p_frame->rtp_head_pos) &= ~RTP_HEADER_EXTENTION_BIT; } RtspPutUintToBufBE((unsigned char *)p_frame->rtp_head_pos + 4, cur_time); if (pSession->rtp_send_data_index >= RTP_MAX_SEND_NUM || desc->frame_end) { int send_pos = p_retry_info->send_pos; int iov_index = 0; int left_size = 0; int send_len = 0; int rtp_index = 0; expectlen = 0; if (send_pos > 0) { while (send_pos >= send_len) { send_len += (pSession->rtp_send_data[rtp_index].rtp_head_size + pSession->rtp_send_data[rtp_index].rtp_playload_size); rtp_index++; } rtp_index--; left_size = send_len - send_pos; if (left_size > pSession->rtp_send_data[rtp_index].rtp_playload_size) { iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_header_data + (pSession->rtp_send_data[rtp_index].rtp_playload_size + pSession->rtp_send_data[rtp_index].rtp_head_size - left_size); iov[iov_index++].iov_len = left_size - pSession->rtp_send_data[rtp_index].rtp_playload_size; expectlen += left_size - pSession->rtp_send_data[rtp_index].rtp_playload_size; left_size = pSession->rtp_send_data[rtp_index].rtp_playload_size; } iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_playload_pos + pSession->rtp_send_data[rtp_index].rtp_playload_size - left_size; iov[iov_index++].iov_len = left_size; expectlen += left_size; rtp_index++; } for (; rtp_index < pSession->rtp_send_data_index; rtp_index++) { iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_header_data; iov[iov_index++].iov_len = pSession->rtp_send_data[rtp_index].rtp_head_size; iov[iov_index].iov_base = pSession->rtp_send_data[rtp_index].rtp_playload_pos; iov[iov_index++].iov_len = pSession->rtp_send_data[rtp_index].rtp_playload_size; expectlen += (pSession->rtp_send_data[rtp_index].rtp_head_size + pSession->rtp_send_data[rtp_index].rtp_playload_size); } ret = RTSPSessionSendV(pSession, iov, iov_index); if (ret == TP_TCP_EC_FAILURE) { pSession->pRTPServer->iRTPStatus = RTP_STATUS_SEND_FAILURE; set_retry_info(p_retry_info, ptr_rtp_package, p_frame->rtp_payload_len); p_retry_info->send_pos = 0; pSession->rtp_send_data_index--; return TP_TCP_EC_FAILURE; } else if(ret != expectlen) // 接收方缓冲区满了,发不出去了 { set_retry_info(p_retry_info, ptr_rtp_package, p_frame->rtp_payload_len); p_retry_info->send_pos += ret > 0 ? ret : 0; pSession->rtp_send_data_index--; return RTSP_SEND_RETRY; } #ifdef SRTP_ENCRYPT_WITH_KEY_NEGOTIATION /* 释放内存 */ if(pSession->pRTPServer->srtp) for (rtp_index = 0; rtp_index < pSession->rtp_send_data_index; rtp_index++) { if(pSession->rtp_send_data[rtp_cur_index].rtp_playload_pos != NULL) { free(pSession->rtp_send_data[rtp_cur_index].rtp_playload_pos); pSession->rtp_send_data[rtp_cur_index].rtp_playload_pos = NULL; pSession->rtp_send_data[rtp_cur_index].rtp_playload_size = 0; } } #endif desc->frame_end = 0; memset(pSession->rtp_send_data, 0, sizeof(RTPSENDDATA)); pSession->rtp_send_data_index = 0; p_retry_info->send_pos = 0; } else { bSendRTCP = FALSE; } } else { MBUFFERByteArray mBuffer; unsigned char TXBufferMemSpace[TPRTSPSERVER_BUFFER_SIZE] = {0}; MBUFFERByteArrayInit(TXBufferMemSpace, 0, 0, TPRTSPSERVER_BUFFER_SIZE - 4, &mBuffer); MBUFFERByteArrayReset(&mBuffer); #if (defined SRTP_SUPPORT) || (defined SRTP_ENCRYPT_WITH_KEY_NEGOTIATION) if (pSession->pRTPServer->srtp) { struct srtp_session *enc_sess = &pSession->pRTPServer->pSessions[iSessionID]->encrypt_session; unsigned int roc = htonl(pSession->pRTPServer->pSessions[iSessionID]->roc_send); unsigned int ssrc = htonl(pSession->pRTPServer->pSessions[iSessionID]->iClientSSRC); unsigned int iv[] = {0x00, ssrc, roc, htonl((pSession->pRTPServer->pSessions[iSessionID]->seq_no) << 16)}; int rtp_payload_len = 0; if (p_frame->rtp_head_len == 14) { memcpy(tmpbuf, p_frame->rtp_head_pos + 12, 2); memcpy(tmpbuf + 2, p_frame->rtp_payload_pos, p_frame->rtp_payload_len); rtp_payload_len = 2 + p_frame->rtp_payload_len; MBUFFERByteArrayPutMultiUCharBE((unsigned char *)p_frame->rtp_head_pos, 12, &mBuffer); } else { memcpy(tmpbuf, p_frame->rtp_payload_pos, p_frame->rtp_payload_len); rtp_payload_len = p_frame->rtp_payload_len; MBUFFERByteArrayPutMultiUCharBE((unsigned char *)p_frame->rtp_head_pos, p_frame->rtp_head_len, &mBuffer); } tpsocket_aes_cm_encrypt((unsigned char *)tmpbuf, (unsigned char *)tmpbuf, rtp_payload_len, &enc_sess->aes_key, (unsigned char *)enc_sess->rtp_salt, (unsigned char *)&iv); MBUFFERByteArrayPutMultiUCharBE((unsigned char *)tmpbuf, rtp_payload_len, &mBuffer); if (enc_sess->auth_len) { char hash[20]; struct tpsocket_sha sha; memcpy(&sha, &enc_sess->sha, sizeof(sha)); tpsocket_sha_update(&sha, mBuffer.pucBuffer, mBuffer.iCurPos); tpsocket_sha_update(&sha, &roc, sizeof(roc)); tpsocket_sha_final(&sha, (unsigned char *)hash); tpsocket_sha_init(&sha); tpsocket_sha_update(&sha, enc_sess->sha_opad, sizeof(enc_sess->sha_opad)); tpsocket_sha_update(&sha, hash, sizeof(hash)); tpsocket_sha_final(&sha, (unsigned char *)hash); MBUFFERByteArrayPutMultiUCharBE((unsigned char *)hash, enc_sess->auth_len, &mBuffer); // 20 bytes in total, low 10 bytes picked only } } else #endif { MBUFFERByteArrayPutMultiUCharBE((unsigned char *)p_frame->rtp_head_pos, p_frame->rtp_head_len, &mBuffer); if(externtionlen > 0) { MBUFFERByteArrayPutMultiUCharBE(RTPextern, externtionlen, &mBuffer); } MBUFFERByteArrayPutMultiUCharBE(sendmute ? mutebuf : p_frame->rtp_payload_pos, p_frame->rtp_payload_len, &mBuffer); } MBUFFERByteConvert2ReadBuff(&mBuffer); #ifdef RTP_RETANS_SUPPORT save_rtppackge_2_retrans_queue(pSession->pRTPServer, iSessionID, &mBuffer, ptr_rtp_package->is_iframe); #endif TPUdpSendByBuffer(pSession->pRTPServer->pSessions[iSessionID]->DataServer, &mBuffer); /*还原设置的拓展标记,避免对其他会话的影响*/ if(*(p_frame->rtp_head_pos) & RTP_HEADER_EXTENTION_BIT) { *(p_frame->rtp_head_pos) &= ~RTP_HEADER_EXTENTION_BIT; } RtspPutUintToBufBE((unsigned char *)p_frame->rtp_head_pos + 4, cur_time); } /* send rtcp/srtcp */ ullTimeSent = tpgetboottime(); // get current time here ptprtpsessioncontext = pSession->pRTPServer->pSessions[iSessionID]; if (bSendRTCP) { pSession->pRTPServer->pSessions[ptr_rtp_package->stream_type]->uiNumPacketsSent++; pSession->pRTPServer->pSessions[ptr_rtp_package->stream_type]->iOctetsSent += iSize; } //根据video的session是否收到RR为标准,来确定audio和video的sr频率 if (pSession->pRTPServer->pSessions[RTP_SESSION_VIDEO]->SRFlag == 1) { send_freq = RTP_RECEIVER_REPORT_INTERVAL; } else { send_freq = RTP_RECEIVER_REPORT_INTERVAL_HF; } if (ullTimeSent - ptprtpsessioncontext->ullLastSRTime >= send_freq && bSendRTCP) { if(pSession->bRTPOverTCP)/* additional 4 bytes are used for reusing TCP channel */ { MBUFFERByteArrayPutUIntBE(0, &(ptprtpsessioncontext->ControlFrame2Send.ByteArray)); } RTPCONTROLSENDERREPORT RTCPSenderReport; #ifdef SRTP_SUPPORT if(strcmp(pSession->pcClientIP, "127.0.0.1") == 0) { uSSRC = ptprtpsessioncontext->iClientSSRC; // webrtc方案时使用远端透传的ssrc } else { uSSRC = ptr_rtp_package->PayloadContext.RTPHeader.ulSSRC; } #else uSSRC = ptr_rtp_package->PayloadContext.RTPHeader.ulSSRC; #endif RTCPSenderReport.uiSsrc = uSSRC; RTCPSenderReport.uiRTPTS = rtp_timestamp; RTCPSenderReport.uiNumOctetsSent = ptprtpsessioncontext->iOctetsSent; RTCPSenderReport.uiNumPacketsSent = ptprtpsessioncontext->uiNumPacketsSent; /* * NTP TimeStamp is a 64-bit fix-point number * with the integer part in the first 32 bits, * and the fractional part in the last 32 bits. */ clock_gettime(CLOCK_REALTIME, &CurTimeSpec); RTCPSenderReport.uiNTPSec = TIME_OFFSET + CurTimeSpec.tv_sec; RTCPSenderReport.uiNTPFrac = CurTimeSpec.tv_nsec; RTPControlBuildSR(&RTCPSenderReport, 0, NULL, &(ptprtpsessioncontext->ControlFrame2Send)); ptprtpsessioncontext->ullLastSRTime = ullTimeSent; ptprtpsessioncontext->SDESFrame.uiSrc = uSSRC; RTPControlBuildSDES(&(pSession->pRTPServer->pSessions[iSessionID]->SDESFrame), &(pSession->pRTPServer->pSessions[iSessionID]->ControlFrame2Send)); #if (defined SRTP_SUPPORT) || (defined SRTP_ENCRYPT_WITH_KEY_NEGOTIATION) MBUFFERByteArray *pByteArray = &pSession->pRTPServer->pSessions[iSessionID]->ControlFrame2Send.ByteArray; #endif if(pSession->bRTPOverTCP) { iSize = MBUFFERByteArrayCurPos(&ptprtpsessioncontext->ControlFrame2Send.ByteArray); MBUFFERByteArraySeek(0,&ptprtpsessioncontext->ControlFrame2Send.ByteArray); MBUFFERByteArrayPutUChar('$', &ptprtpsessioncontext->ControlFrame2Send.ByteArray); MBUFFERByteArrayPutUChar(ptprtpsessioncontext->iTCPControlID, &ptprtpsessioncontext->ControlFrame2Send.ByteArray); #ifdef SRTP_ENCRYPT_WITH_KEY_NEGOTIATION if (pSession->pRTPServer->srtp) {/* iSize-4:4字节rtsp长度减去,+ 4:payload以及校验位之间的u_int(4字节)rtcp_seq_no */ MBUFFERByteArrayPutUShortBE(iSize - 4 + pSession->pRTPServer->pSessions[iSessionID]->encrypt_session.auth_len + sizeof(unsigned int), &ptprtpsessioncontext->ControlFrame2Send.ByteArray); } else #endif { MBUFFERByteArrayPutUShortBE(iSize - 4, &ptprtpsessioncontext->ControlFrame2Send.ByteArray); } MBUFFERByteArraySeek(iSize, &ptprtpsessioncontext->ControlFrame2Send.ByteArray); } #if (defined SRTP_SUPPORT) || (defined SRTP_ENCRYPT_WITH_KEY_NEGOTIATION) if (pSession->pRTPServer->srtp) { struct srtp_session *enc_sess = &pSession->pRTPServer->pSessions[iSessionID]->encrypt_session; unsigned int ssrc = htonl(pSession->pRTPServer->pSessions[iSessionID]->iClientSSRC); unsigned int iv[] = {0x00, ssrc, htonl((pSession->pRTPServer->pSessions[iSessionID]->rtcp_seq_no) >> 16), htonl((pSession->pRTPServer->pSessions[iSessionID]->rtcp_seq_no) << 16)}; int rtcp_payload_len = pByteArray->iCurPos - 8; unsigned char * rtcp_payload_pos = pByteArray->pucBuffer + 8; tpsocket_aes_cm_encrypt((unsigned char *)rtcp_payload_pos, (unsigned char *)rtcp_payload_pos, rtcp_payload_len, &enc_sess->aes_key2, (unsigned char *)enc_sess->rtcp_salt, (unsigned char *)&iv); MBUFFERByteArrayPutUIntBE(pSession->pRTPServer->pSessions[iSessionID]->rtcp_seq_no + (unsigned int)2147483648u, pByteArray); if (enc_sess->auth_len) { char hash[20]; struct tpsocket_sha sha; memcpy(&sha, &enc_sess->sha1, sizeof(sha)); if(pSession->bRTPOverTCP) {/* 计算校验的时候,前面4字节rtsp不能算进去 */ tpsocket_sha_update(&sha, pByteArray->pucBuffer+4, pByteArray->iCurPos-4); } else { tpsocket_sha_update(&sha, pByteArray->pucBuffer, pByteArray->iCurPos); } tpsocket_sha_final(&sha, (unsigned char *)hash); tpsocket_sha_init(&sha); tpsocket_sha_update(&sha, enc_sess->sha_opad1, sizeof(enc_sess->sha_opad1)); tpsocket_sha_update(&sha, hash, sizeof(hash)); tpsocket_sha_final(&sha, (unsigned char *)hash); MBUFFERByteArrayPutMultiUCharBE((unsigned char *)hash, enc_sess->auth_len, pByteArray); // 20 bytes in total, low 10 bytes picked only } } pSession->pRTPServer->pSessions[iSessionID]->rtcp_seq_no++; #endif RTP4SWriteControl(pSession->pRTPServer, iSessionID); } #if (defined SRTP_SUPPORT) || (defined SRTP_ENCRYPT_WITH_KEY_NEGOTIATION) if (strcmp(pSession->pcClientIP, "127.0.0.1") == 0 #ifdef SRTP_ENCRYPT_WITH_KEY_NEGOTIATION || pSession->pRTPServer->srtp #endif ) { pSession->pRTPServer->pSessions[iSessionID]->seq_no++; if (!pSession->pRTPServer->pSessions[iSessionID]->seq_no) { pSession->pRTPServer->pSessions[iSessionID]->roc_send++; } } else #endif { pSession->pRTPServer->pSessions[iSessionID]->rtp_seq++ ; } reset_retry_info(p_retry_info, ptr_rtp_package); return 0; } int TPRtspExecute(TPRTSPSERVER *pRtspServer) { struct sockaddr_in ClientAddr; int iClientAddrlen = sizeof(struct sockaddr_in); int iClientSocket; char pcClientIP[TP_TCP_CLIENT_IP_SIZE]; if (!pRtspServer) { return TP_TCP_EC_FAILURE; } if ((iClientSocket = accept(pRtspServer->iSock, (struct sockaddr *)&ClientAddr, (socklen_t *)&iClientAddrlen)) >= 0) { strncpy(pcClientIP, inet_ntoa(ClientAddr.sin_addr), TP_TCP_CLIENT_IP_SIZE); if (pRtspServer->pOnAcceptSucceededCallback != NULL) { pRtspServer->pOnAcceptSucceededCallback(iClientSocket, pcClientIP, pRtspServer->pArgs); } else { #ifdef RTSPD_SUPPORT if (TP_TCP_EC_FAILURE == TPRtspOnAccept(pRtspServer, iClientSocket, pcClientIP, NULL, NEED_AUTHENTICATION_TRUE)) #else if (TP_TCP_EC_FAILURE == TPRtspOnAccept(pRtspServer, iClientSocket, pcClientIP, NEED_AUTHENTICATION_TRUE)) #endif { TPRtspCloseClientSocket(pRtspServer, iClientSocket); } } return TP_TCP_EC_OK; } return TP_TCP_EC_WAIT; } int TPRtspRegisterCallback(TPRTSPSERVER *pRtspServer, PONACCEPTSUCCEEDEDCALLBACK pOnAcceptSucceededCallback, void *pArgs) { RETURN_IVALID_IF(!pRtspServer) pRtspServer->pArgs = pArgs; pRtspServer->pOnAcceptSucceededCallback = pOnAcceptSucceededCallback; return TP_TCP_EC_OK; } int TPRtspCloseSession(TPRTSPSERVER *pRtspServer, int iSessionID) { if ((iSessionID > (TPRTSPSERVER_MAX_SESSION - 1)) || (iSessionID < 0) || !pRtspServer) { return(TPRTSPSERVER_EC_FAILURE); } SYSTEM_DEVSTA dev_sta = {0}; RTSP_INFO_LOG("CloseSession called, %dth in %d", iSessionID, pRtspServer->iNumClients); TPRTSPSERVERSESSION *pRTSPServerSession = pRtspServer->pClients[iSessionID]; if (pRTSPServerSession) { /* pRTSPServerSession->bIsSessionON = 0; */ /* TODO: 暂定Session状态: * 0 - Session closed * 1 - Session running * 2 - Session to be stopped */ pRTSPServerSession->bIsSessionON = 0; RTSPSessionDeinit(pRTSPServerSession); if (pRTSPServerSession->pRTPServer != NULL) { pRTSPServerSession->pRTPServer->bIsRunning = 0; RTP4SDeInit(pRTSPServerSession->pRTPServer); free(pRTSPServerSession->pRTPServer); pRTSPServerSession->pRTPServer = NULL; } free(pRtspServer->pClients[iSessionID]); pRtspServer->pClients[iSessionID] = NULL; RTSP_DEBUG("rtsp session %d deleted.", iSessionID); pRtspServer->iNumClients--; RTSP_DEBUG("Session %d closed, %d remaining", iSessionID, pRtspServer->iNumClients); /* 主子码流数均>=1,认为设备已接入客户端,修改设备二层广播报文中设备状态为1 */ /* 不统计multitrans连接,该字段只有NVR使用,记录设备是否已被其他NVR接入 */ ds_read(SYSTEM_DEVSTA_PATH, &dev_sta, sizeof(SYSTEM_DEVSTA)); if (rtsp_get_client_num_by_type(CLIENT_TYPE_LOCAL, LEFT_BIT(TPRTP_STREAM_ID_MAIN), TRUE) >= 1 && rtsp_get_client_num_by_type(CLIENT_TYPE_LOCAL, LEFT_BIT(TPRTP_STREAM_ID_SUB), TRUE) >= 1) { dev_sta.device_status = 1; } else { dev_sta.device_status = 0; } ds_write(SYSTEM_DEVSTA_PATH, &dev_sta, sizeof(SYSTEM_DEVSTA)); } return(TPRTSPSERVER_EC_OK); } #ifdef RTSPD_SUPPORT int TPRtspOnAccept(TPRTSPSERVER *pRtspServer, int iClientSocket, const char *pcClientIP, TCP_CONNECTION_T * connection, int needAuthentication) #else int TPRtspOnAccept(TPRTSPSERVER *pRtspServer, int iClientSocket, const char *pcClientIP, int needAuthentication) #endif { int i = 0; TPRTSPSERVERSESSION *pSession; static int ip_lock = 0; RTSP_INFO_LOG("New client accessing: %s sock %d", pcClientIP, iClientSocket); /* check if rtsp server is restarting*/ if (pRtspServer->bIsReadytoAccept == 0) { /*rtsp server is on restarting, reject the client */ RTSP_ERROR("RTSP Server is restarting, reject"); return(TP_TCP_EC_FAILURE); } //收到连接后,不允许再改ip了 if(ip_lock == 0) { PROTOCOL_STATUS status; IPCD_STREAM_OFFERED stream_offered = {0}; status.ip_change_forbidden = 1; ds_write(PROTOCOL_STATUS_PATH, &status, sizeof(status)); ds_read(IPCD_STREAM_OFFERED_PATH, &stream_offered, sizeof(IPCD_STREAM_OFFERED)); if (0 == stream_offered.status) { stream_offered.status = 1; ds_advanced_write(IPCD_STREAM_OFFERED_PATH, &stream_offered, sizeof(IPCD_STREAM_OFFERED), DS_FLAG_SAVE_FLASH); } ip_lock =1; } if (pRtspServer->iNumClients < TPRTSPSERVER_MAX_SESSION) { for (i = 0; i < TPRTSPSERVER_MAX_SESSION; i++) { if (pRtspServer->pClients[i] == NULL) { break; } } if (i == TPRTSPSERVER_MAX_SESSION) { RTSP_ERROR("Too much clients, reject"); return(TP_TCP_EC_FAILURE); } pSession = (TPRTSPSERVERSESSION *)malloc(sizeof(TPRTSPSERVERSESSION)); if (pSession == NULL) { RTSP_ERROR("No sufficient memory"); return(TP_TCP_EC_FAILURE); } pthread_mutex_lock(&g_rtsp_mutex); RTSPSessionInit(pSession); pSession->iSessionID = i; pSession->iStatus = SESSION_OPEN; pSession->iSock = iClientSocket; #ifdef RTSPD_SUPPORT pSession->web_connection = connection; #endif memset(pSession->rtp_send_data, 0, sizeof(RTPSENDDATA)); pSession->rtp_send_data_index = 0; #ifdef RTSPD_SUPPORT if(connection != NULL) { pSession->ssl = connection->ssl; pSession->tpssl = connection->tpssl; pSession->webparam = (webParam_t *)connection->param; } else { pSession->ssl = NULL; pSession->tpssl = NULL; pSession->webparam = NULL; } #endif strncpy(pSession->pcClientIP, pcClientIP, 32); SDPInit(&pSession->SDPServer); pSession->pcServerIP = pRtspServer->pcServerIP; pSession->iServerPort = pRtspServer->iPort; RTSPSessionGenerateSessionID(pSession); TPRtspUpdateServerIP(pRtspServer); SDPSetServerIP(&pSession->SDPServer, pRtspServer->pcServerIP); pSession->rtspAuthManeger = pRtspServer->rtspAuthManeger; RTSPSessionSetNonBlock(pSession, 1); /* 设为非阻塞socket */ RTSPSessionSetKeepalive(pSession, 20, 5, 3); /* 设置主动探活,网络异常超过30s,则判为连接失效 */ RTSPSessionSetSendBuf(pSession, get_main_stream_send_buf()); /* 设置SNDBUF发送缓冲区大小 */ RTSPSessionSetRecvBuf(pSession, TPPLAYER_RECVBUF_SIZE); /* smart encoder related */ SDPEnableVirtualIFrame(&pSession->SDPServer, pRtspServer->bIsVirtualIFrameEnabled); #ifdef SRTP_SUPPORT if (pRtspServer->iNeedAuthentication && needAuthentication && strcmp(pcClientIP, "127.0.0.1") != 0) #else if (pRtspServer->iNeedAuthentication && needAuthentication) #endif { pSession->iNeedAuthentication = 1; } #ifdef SRTP_SUPPORT if (strcmp(pcClientIP, "127.0.0.1") == 0) { pSession->bIsSrtp = 1; } #endif if (strcmp(pcClientIP, "localhost") == 0) { pSession->bIsLocalHost = 1; } pRtspServer->pClients[i] = pSession; pRtspServer->iNumClients++; pthread_mutex_unlock(&g_rtsp_mutex); } else { RTSP_ERROR("Too much clients, reject"); return(TP_TCP_EC_FAILURE); } RTSP_INFO_LOG("Accept client with iSessionID %d", i); return(TPRTSPSERVER_EC_OK); } int TPRtspStart(TPRTSPSERVER *pRtspServer) { int iRet = TPRTSPSERVER_EC_OK; RETURN_IVALID_IF(!pRtspServer) if (TPRtspSocketInit(pRtspServer) != TP_TCP_EC_OK) { RTSP_ERROR("error : RTSP socket init fail"); iRet = TPRTSPSERVER_EC_FAILURE; } return(iRet); } int TPRtspStop(TPRTSPSERVER *pRtspServer) { int iRet = TPRTSPSERVER_EC_OK; RETURN_IVALID_IF(!pRtspServer); pRtspServer->bIsRunning = 0; TPRtspDeInit(pRtspServer); TPRtspClose(pRtspServer); return(iRet); } int TPRtspSetAuthentication(TPRTSPSERVER *pRtspServer, char *pcUsername[TPRTSPSERVER_MAX_USER_NUM], char *pcPassword[TPRTSPSERVER_MAX_USER_NUM], int iUserNum) { int i; char pcAuthenticationRaw[RTSP_USERNAME_LENGTH * 2]; FACTORY_TEST_MODE factory_test_mode = {0}; RETURN_IVALID_IF(!pRtspServer) if (iUserNum > TPRTSPSERVER_MAX_USER_NUM) { iUserNum = TPRTSPSERVER_MAX_USER_NUM; } pRtspServer->iNeedAuthentication = 1; for (i = 0; i < iUserNum; i++) { if ((NULL == pcUsername[i]) || (NULL == pcPassword[i])) { RTSP_ERROR("error : something wrong happened, skip this user"); continue; } ds_read(FACTORY_TEST_MODE_PATH, &factory_test_mode, sizeof(factory_test_mode)); if (factory_test_mode.enabled == 1) { pRtspServer->iNeedAuthentication = 0; } strncpy(pRtspServer->pcUsername[i], pcUsername[i], RTSP_USERNAME_LENGTH); strncpy(pRtspServer->pcPassword[i], pcPassword[i], RTSP_USERNAME_LENGTH); snprintf(pcAuthenticationRaw, RTSP_USERNAME_LENGTH * 2, "%s:%s", pcUsername[i], pcPassword[i]); /* 格式"admin:tplink12345"; */ tpssl_base64Encode(pcAuthenticationRaw, strlen(pcAuthenticationRaw), pRtspServer->pcBaseAuthenticationCoded[i]); } pRtspServer->iUserNum = iUserNum; return(RTSP_EC_OK); } /** * UpdateTimeout * @abstract 外部通过NPT服务器、NVR、APP或者Web页面更改IPC系统时间,可能错误地触发Server超时机制。 * 因此需要在系统时间更改时,调用该接口告知Server更新内部记录的时间标识; * * @param[in] ulTargetTime 目标时间,单位毫秒 * @param[in] ulCurrentTime 当前时间,单位毫秒 * * @return 更新成功返回0 */ int TPRtspUpdateTimeout(TPRTSPSERVER *pRtspServer, unsigned long long ulTargetTime, unsigned long long ulCurrentTime) { int i = 0, j = 0; TPRTSPSERVERSESSION *pSession; TPRTPSESSIONCONTEXT *pRTPSession; for (i = 0; i < TPRTSPSERVER_MAX_SESSION; i++) { pthread_mutex_lock(&g_rtsp_mutex); if (pRtspServer->pClients[i] != NULL) { RTSPSessionUpdateTimeout(pRtspServer->pClients[i], ulTargetTime, ulCurrentTime); pSession = (TPRTSPSERVERSESSION *)(pRtspServer->pClients[i]); if (pSession->pRTPServer) { for (j = 0; j < RTP_SESSION_NUM; j++) { pRTPSession = pSession->pRTPServer->pSessions[j]; if (pRTPSession && pRTPSession->DataServer) { TPUdpUpdateTimeout(pRTPSession->DataServer, ulTargetTime, ulCurrentTime); } } } } pthread_mutex_unlock(&g_rtsp_mutex); } return(RTSP_EC_OK); } int TPRtspAuthenticate(TPRTSPSERVER *pRtspServer, MBUFFERByteArray *pByteArray, char *pcRequestType, char *pcServerNouce) { int iRet = TPRTSP_AUTHENTICATION_FAILURE; int i; char pcUserName[RTSP_USERNAME_LENGTH]; char pcRealm[RTSP_USERNAME_LENGTH]; char pcNonce[RTSP_USERNAME_LENGTH]; char pcUri[RTSP_USERNAME_LENGTH]; char pcAlgorithm[RTSP_USERNAME_LENGTH]; char pcResponse[RTSP_USERNAME_LENGTH]; /* 客户端传来的认证字符串 */ char *pcPassword = NULL; char pcResponseServer[RTSP_USERNAME_LENGTH];/* server 端计算的认证字符串 */ char HA1Hex[TS_HASH_HEX_SIZE + 1] = {0}; /* 中间结果 */ char pcWhiteSpaces[4] = {'=', ' ', '\t', ','}; RETURN_IVALID_IF(!pRtspServer || !pByteArray) MBUFFERByteArraySetWhiteSpaces(pcWhiteSpaces, 4, pByteArray); if (pRtspServer->iNeedAuthentication == 0) { iRet = TPRTSP_AUTHENTICATION_OK; } else if (pRtspServer->iUserNum == 0) { iRet = TPRTSP_AUTHENTICATION_FAILURE; } else if (strlen(pRtspServer->pcUsername[0]) == 0) { iRet = TPRTSP_AUTHENTICATION_FAILURE; } else if ((MBUFFERByteArrayPeekString((char *)"Digest", pByteArray)) == 0) { MBUFFERByteArrayAdvance(strlen((char *)"Digest"), pByteArray); while (MBUFFERByteArrayLength(pByteArray) > 0) { if (MBUFFERByteArrayFindStringNCase((char *)"username=\"", pByteArray) == MBUFFER_EC_OK) { MBUFFERByteArrayGetStringBySeparator(pcUserName, RTSP_USERNAME_LENGTH, '\"', pByteArray); } else if (MBUFFERByteArrayFindStringNCase((char *)"realm=\"", pByteArray) == MBUFFER_EC_OK) { MBUFFERByteArrayGetStringBySeparator(pcRealm, RTSP_USERNAME_LENGTH, '\"', pByteArray); } else if (MBUFFERByteArrayFindStringNCase((char *)"nonce=\"", pByteArray) == MBUFFER_EC_OK) { MBUFFERByteArrayGetStringBySeparator(pcNonce, RTSP_USERNAME_LENGTH, '\"', pByteArray); } else if (MBUFFERByteArrayFindStringNCase((char *)"uri=\"", pByteArray) == MBUFFER_EC_OK) { MBUFFERByteArrayGetStringBySeparator(pcUri, RTSP_USERNAME_LENGTH, '\"', pByteArray); } else if (MBUFFERByteArrayFindStringNCase((char *)"response=\"", pByteArray) == MBUFFER_EC_OK) { MBUFFERByteArrayGetStringBySeparator(pcResponse, RTSP_USERNAME_LENGTH, '\"', pByteArray); } else if (MBUFFERByteArrayFindStringNCase((char*)"algorithm=\"", pByteArray) == MBUFFER_EC_OK) { /* We default the algorithm to MD5, so the value of 'pcAlgorithm' is actually not being used */ MBUFFERByteArrayGetStringBySeparator(pcAlgorithm, RTSP_USERNAME_LENGTH, '\"', pByteArray); } else { return iRet; } } if ((strlen(pcRealm) == strlen(gpucRTSPRealm)) && (strncasecmp(pcRealm, gpucRTSPRealm, strlen(gpucRTSPRealm)) != 0)) { return iRet; } if ((strlen(pcNonce) == strlen(pcServerNouce)) && (strncasecmp(pcNonce, pcServerNouce, RTSP_AUTH_NOUCE_LENGTH) != 0)) { return iRet; } for (i = 0; i < pRtspServer->iUserNum; i++) { if (strncmp(pcUserName, pRtspServer->pcUsername[i], RTSP_USERNAME_LENGTH) == 0) { pcPassword = pRtspServer->pcPassword[i]; break; } } if (pcPassword == NULL) { return iRet; } DIGEST_AUTH_ITEM digestItem; memset(&digestItem, 0, sizeof(DIGEST_AUTH_ITEM)); digestItem.pName = pcUserName; digestItem.pPswd = pcPassword; digestItem.pUri = pcUri; digestItem.pNonce = pcNonce; digestItem.pRealm = pcRealm; /* Calc HA1 */ DigestCalcHA1( digestItem.pAlg, digestItem.pName, digestItem.pRealm, digestItem.pPswd, digestItem.pNonce, digestItem.pCnonce, HA1Hex); /* Calc response */ digestItem.pRespons = (char *)pcResponseServer; DigestCalcResponse( HA1Hex, digestItem.pNonce, digestItem.pNc, digestItem.pCnonce, digestItem.pQop, pcRequestType, digestItem.pUri, NULL, pcResponseServer); RTSP_DEBUG("pcResponse:%s, pcResponseServer:%s", pcResponse, pcResponseServer); if (strncmp(pcResponseServer, pcResponse, RTSP_USERNAME_LENGTH) == 0) { iRet = TPRTSP_AUTHENTICATION_OK; } } else if (MBUFFERByteArrayPeekString((char *)"Basic", pByteArray) == 0) { /* 客户端发来"Basic xxxx"鉴权信息 */ MBUFFERByteArrayAdvance(strlen((char *)"Basic"), pByteArray); /* 取得" xxxx" */ MBUFFERByteArraySkipWhiteSpaces(pByteArray); /* 去除空格,取得"xxxx" */ for (i = 0; i < pRtspServer->iUserNum; i++) { if (MBUFFERByteArrayLength(pByteArray) != strlen(pRtspServer->pcBaseAuthenticationCoded[i])) { iRet = TPRTSP_AUTHENTICATION_FAILURE; break; } if (strncmp((const char *)MBUFFERByteArrayCurBufferPos(pByteArray), (const char *)pRtspServer->pcBaseAuthenticationCoded[i], strlen(pRtspServer->pcBaseAuthenticationCoded[i])) == 0) { iRet = TPRTSP_AUTHENTICATION_OK; break; } } } return iRet; } int TPRtspUpdateServerIP(TPRTSPSERVER *pRtspServer) { /* get local ip address */ char ppcIP[4][TP_IP_MAX_LEN]; int iNumIP, iCount = 4; int i; RETURN_IVALID_IF(!pRtspServer) for (i = 0; i < iCount; i++) { ppcIP[i][0] = '\0'; } iNumIP = GetLocalIP(ppcIP, NULL, iCount); if (iNumIP > 0) { /* For the time being, use the first valid IP addr. */ strncpy(pRtspServer->pcServerIP, ppcIP[0], strlen(ppcIP[0]) + 1); } else { RTSP_ERROR("Failed to get Server IP!"); return(TPRTSPSERVER_EC_FAILURE); } return(TPRTSPSERVER_EC_OK); } int TPRtspSetMediaInfo(TPRTSPSERVER *pRtspServer, int iSession, TPMEDIAINFO *pMediaInfo) { RETURN_IVALID_IF(!pRtspServer) if ((iSession < 0) || (iSession > TPRTSPSERVER_MAX_SESSION - 1)) { return(TPRTSPSERVER_EC_FAILURE); } TPRTSPSERVERSESSION *pSession = (TPRTSPSERVERSESSION *)pRtspServer->pClients[iSession]; TPMEDIAINFO *pSessionMediaInfo = &pSession->SDPServer.SDPInfo.MediaInfo; memcpy(pSessionMediaInfo, pMediaInfo, sizeof(struct TPMEDIAINFO)); return(TPRTSPSERVER_EC_OK); } int TPRtspSetMultiCastSocket(TPRTSPSERVER *pRtspServer, int iSession, char *pcIP, int iPort, int iPortAudio) { TPRTSPSERVERSESSION *pSession; if ((iSession < 0) || (iSession > TPRTSPSERVER_MAX_SESSION - 1) || !pRtspServer) { return(TPRTSPSERVER_EC_FAILURE); } pSession = (TPRTSPSERVERSESSION *)pRtspServer->pClients[iSession]; RTSPSessionSetMultiCastConfig(pSession, pcIP, iPort); SDPSetMultiCastConfig(&pSession->SDPServer, pcIP, iPort, iPortAudio); return(TPRTSPSERVER_EC_OK); } int TPRtspSetServerReady(TPRTSPSERVER *pRtspServer, int iReady) { RETURN_IVALID_IF(!pRtspServer) pRtspServer->bIsReadytoAccept = iReady; return(TPRTSPSERVER_EC_OK); } int TPRtspEnableVirtualIFrame(TPRTSPSERVER *pRtspServer, int bIfEnable) { RETURN_IVALID_IF(!pRtspServer) pRtspServer->bIsVirtualIFrameEnabled = bIfEnable; return(TPRTSPSERVER_EC_OK); } int TPRtspGetAudioClientNum(TPRTSPSERVER *pRtspServer) { int iAudioNum = 0, i = 0; RETURN_IVALID_IF(!pRtspServer) for (i = 0; i < TPRTSPSERVER_MAX_SESSION; i++) { pthread_mutex_lock(&g_rtsp_mutex); if (pRtspServer->pClients[i]) { TPRTSPSERVERSESSION *pSession = (TPRTSPSERVERSESSION *)(pRtspServer->pClients[i]); if (pSession->iAudioVideo & RTSP_AUDIO) { iAudioNum++; } } pthread_mutex_unlock(&g_rtsp_mutex); } return iAudioNum; } ——详解一下这里面digest认证的实现
09-16
static struct tphttp_session* tphttp_session_new(struct tphttp_server* server) { int count = 0; struct tphttp_session* session = NULL, * nsession = NULL, *psession = NULL; psession = malloc(sizeof(*psession)); if (!psession) { return NULL; } memset(psession, 0, sizeof(*psession)); INIT_LIST_HEAD(&psession->list); psession->tmo.cb = tphttp_session_timeout; psession->server = server; psession->realm = strdup(server->digest_realm ? server->digest_realm : "smarthome@tp-link.com"); psession->cookie = malloc(33); psession->cookie[32] = 0; do { tpsocket_hex_random(psession->cookie, 32, 0); } while (tphttp_session_find_cookie(server, psession->cookie)); DEBUG_SESS("SESSION NEW %p COOKIE %s SESSIONS=%d\n", session, psession->cookie, server->session_count); if (server->session_count < server->max_session) { goto end; } list_for_each_entry(session, &server->session, list) { if (!(session->authed & TPHTTP_AUTH_OK)) { count++; } } if (count > server->session_count/4) { list_for_each_entry_safe_reverse(session, nsession, &server->session, list) { if (!(session->authed & TPHTTP_AUTH_OK)) { DEBUG_SESS("SESSION PURGING UNAUTHED %p\n", session); tphttp_session_free(session); if (server->session_count < server->max_session) { goto end; } } } } list_for_each_entry_safe_reverse(session, nsession, &server->session, list) { DEBUG_SESS("SESSION PURGING AUTHED %p\n", session); tphttp_session_free(session); if (server->session_count < server->max_session) { goto end; } } end: server->session_count ++; list_add_tail(&psession->list, &server->session); tpsocket_pthread_timeout_set(server->handler.sp, &psession->tmo, server->session_short?server->session_short:60*1000); return psession; } void tphttp_session_set_authed(struct tphttp_session*session) { session->authed |= TPHTTP_AUTH_OK; tphttp_session_refresh(session); } static bool tphttp_session_check_token(struct tphttp_session*session) { struct tphttp_credential*c = NULL; struct tphttp_server* server = session->server; if (session->token) { list_for_each_entry(c, &server->credential, list) { if (c->auth_type == TPHTTP_AUTH_TOKEN && strsame(session->token, c->param2) && (!c->param1 || (session->cookie && strsame(session->cookie, c->param1)))) { return true; } } } return false; } static struct tphttp_service *tphttp_service_get(struct tphttp_server* server, const char* uri, int http_method) { int i = 0, count = server->service_num, retry = 0; struct tphttp_service*service = server->service; do_retry: for (i = 0; i < count; i++) { if (!service[i].path || (!retry && strsame(uri, service[i].path)) || (retry && strwithprefix(uri, service[i].path))) { if (retry) { int len = strlen(service[i].path) ; if (uri[len] != '/' && service[i].path[len - 1] != '/') { continue; } } if (http_method == HTTP_REQUEST_GET && !(service[i].method&(TPHTTP_METHOD_GET|TPHTTP_METHOD_ANY))) { continue; } if (http_method == HTTP_REQUEST_POST && !(service[i].method&(TPHTTP_METHOD_POST|TPHTTP_METHOD_ANY))) { continue; } return &service[i]; } } if (!retry) { retry = 1; goto do_retry; } return NULL; } bool tphttp_authentication_check(struct tphttp_auth_info *auth_info, int auth_type, const char *name, const char *pswd) { if (auth_info && name && pswd) { if (auth_type == TPHTTP_AUTH_BASIC) { int ul = strlen(name); if (auth_info->basic && strwithprefix(auth_info->basic, name) && auth_info->basic[ul] == ':' && strsame(auth_info->basic + ul + 1, pswd)) { return true; } } else if (auth_type == TPHTTP_AUTH_DIGEST) { #ifdef HTTP_HMAC_HKDF_SUPPORT if (strcasesame(auth_info->algorithm, "SHA-256")) { char tmp_ha1_sha256[256] = {0}; digest_calc_ha1_sha256(name, auth_info->realm, pswd, tmp_ha1_sha256); char tmp_response_sha256[256] = {0}; if (auth_info->method == HTTP_REQUEST_GET) { digest_calc_response_sha256(tmp_ha1_sha256, auth_info->nonce, auth_info->nc_s, auth_info->cnonce, auth_info->qop, "GET", auth_info->uri, tmp_response_sha256); } else if (auth_info->method == HTTP_REQUEST_POST) { digest_calc_response_sha256(tmp_ha1_sha256, auth_info->nonce, auth_info->nc_s, auth_info->cnonce, auth_info->qop, "POST", auth_info->uri, tmp_response_sha256); } if (strsame(auth_info->digest, tmp_response_sha256)) { return true; } } else #endif { md5_ctx_t ctx; unsigned char md51[33] = {0}, md52[33] = {0}; int nc = 0; char *end = NULL; /* HA1(MD5) = H(username:realm:password)*/ md5_begin(&ctx); md5_hash(name, strlen(name), &ctx); md5_hash(":", 1, &ctx); md5_hash(auth_info->realm, strlen(auth_info->realm), &ctx); md5_hash(":", 1, &ctx); md5_hash(pswd, strlen(pswd), &ctx); md5_end(md51+16, &ctx); tpsocket_hex_encode(md51+16, 16, md51, 0); if (strcasesame(auth_info->algorithm, "MD5-sess")) { /* HA1(MD5-sess) = H(A1(MD5):nonce:cnonce)*/ md5_begin(&ctx); md5_hash(md51, 32, &ctx); md5_hash(":", 1, &ctx); md5_hash(auth_info->nonce, strlen(auth_info->nonce), &ctx); md5_hash(":", 1, &ctx); md5_hash(auth_info->cnonce, strlen(auth_info->cnonce), &ctx); md5_end(md51+16, &ctx); tpsocket_hex_encode(md51+16, 16, md51, 0); } /* HA2 = H(method:uri)*/ md5_begin(&ctx); if (auth_info->method == HTTP_REQUEST_GET) { md5_hash("GET:", 4, &ctx); } else { md5_hash("POST:", 5, &ctx); } md5_hash(auth_info->uri, strlen(auth_info->uri), &ctx); md5_end(md52+16, &ctx); tpsocket_hex_encode(md52+16, 16, md52, 0); /* Response = H(HA1:nonce:nc:cnonce:qop:HA2)*/ md5_begin(&ctx); md5_hash(md51, 32, &ctx); md5_hash(":", 1, &ctx); md5_hash(auth_info->nonce, strlen(auth_info->nonce), &ctx); md5_hash(":", 1, &ctx); md5_hash(auth_info->nc_s, strlen(auth_info->nc_s), &ctx); md5_hash(":", 1, &ctx); md5_hash(auth_info->cnonce, strlen(auth_info->cnonce), &ctx); md5_hash(":", 1, &ctx); md5_hash(auth_info->qop, strlen(auth_info->qop), &ctx); md5_hash(":", 1, &ctx); md5_hash(md52, 32, &ctx); md5_end(md51+16, &ctx); tpsocket_hex_encode(md51+16, 16, md51, 0); nc = strtoul(auth_info->nc_s, (char**)&end, 16); if (!end || end <= auth_info->nc_s) { nc = 0; } DEBUG_CRED("response = %s vs %s nc = %d\n", auth_info->digest, md51, nc); if (strsame(auth_info->digest, md51)) { return true; } } } } return false; } static bool tphttp_auth_check_def_cb(struct tphttp_auth_info *auth_info, int auth_type, const char *name, const char *pswd, void *priv) { return tphttp_authentication_check(auth_info, auth_type, name, pswd); } static struct tphttp_session* tphttp_session_get(struct tphttp_connection* conn, struct list_head*mbuf, const char*addr, int method) { struct tphttp_credential*c = NULL, *authed_c = NULL; struct tphttp_server *server = conn->server; struct tphttp_session* session = NULL, * psession = NULL; struct tpsocket_buf* buf = NULL; unsigned int nc = 0, http_auth = 0, authed = TPHTTP_AUTH_NONE; char *cookie = NULL, *token = NULL; char *username = NULL, *opaque = NULL; char *http_host = NULL, *http_referer = NULL; struct tphttp_env*env = NULL; struct tphttp_auth_info auth_info = {NULL}; list_for_each_entry(env, &conn->hdr, list) { const char *p = env->value, *t = NULL; if (!cookie && strcasesame("Cookie", env->name)) { t = strstr(p, "TP_HTTP_COOKIE="); if (t) { p = t + 15; t = strchr(p, ';'); if (!t) { t = strchr(p, ' '); if (!t) { t = strchr(p, '\t'); } } if (t) { cookie = strndup(p, t - p); } else { cookie = strdup(p); } } } else if (!token && strcasesame("X-Token", env->name)) { token = strdup(p); } else if (!http_auth && strcasesame("Authorization", env->name)) { int kl = 0, vl = 0; const char *k = NULL, *v = NULL; if (strcasewithprefix(p, "Basic")) { http_auth = TPHTTP_AUTH_BASIC; } else if (strcasewithprefix(p, "Digest")) { http_auth = TPHTTP_AUTH_DIGEST; } else { continue; } while(*p && (*p!=' '&&*p!='\t'))p++; if (http_auth == TPHTTP_AUTH_BASIC) { while(*p==' '||*p=='\t')p++; v = p; while(*p && (*p!=' '&&*p!='\t'))p++; vl = p - v; auth_info.basic = strndup(v, vl); if (auth_info.basic) { vl = tpsocket_base64_decode(auth_info.basic, vl, auth_info.basic); if (vl > 0) { auth_info.basic[vl] = 0; } else { free(auth_info.basic); auth_info.basic = NULL; } } } else if (http_auth == TPHTTP_AUTH_DIGEST) { while (*p) { while(*p==' '||*p=='\t'||*p==','||*p=='"')p++; k = p; while(*p && (*p!=' '&&*p!='\t'&&*p!='='))p++; kl = p - k; while(*p==' '||*p=='='||*p=='\t')p++; if (*p == '=') p++; v = p; if (*p == '"') { p++; v++; while(*p && (*p!='"'))p++; } else { while(*p && (*p!=','))p++; } vl = p -v; if (/**p && */vl) { if (strncasematch("username", k, kl)) { username = strndup(v, vl); } else if (strncasematch("realm", k, kl)) { auth_info.realm = strndup(v, vl); } else if (strncasematch( "nonce", k, kl)) { auth_info.nonce = strndup(v, vl); } else if (strncasematch("cnonce", k, kl)) { auth_info.cnonce = strndup(v, vl); } else if (strncasematch("uri", k, kl)) { auth_info.uri = strndup(v, vl); } else if (strncasematch("response", k, kl)) { auth_info.digest = strndup(v, vl); } else if (strncasematch("opaque", k, kl)) { opaque = strndup(v, vl); } else if (strncasematch("qop", k, kl)) { auth_info.qop = strndup(v, vl); } else if (strncasematch("algorithm", k, kl)) { auth_info.algorithm = strndup(v, vl); } else if (strncasematch("nc", k, kl)) { auth_info.nc_s = strndup(v, vl); nc = strtoul(v, (char**)&k, 16); if (!k || k <= v) { nc = 0; } } else { } } } auth_info.method = method; } } else if (server->referer_check && strcasesame("Referer", env->name)) { http_referer = strdup(p); } else if (server->referer_check && strcasesame("Host", env->name)) { http_host = strdup(p); } } if (server->referer_check) { int check_result = true; if (http_host && http_referer) { int conn_type; char * host = NULL, *port = NULL, *http_port = strchr(http_host, ':'); //DEBUG("HOST %s!\n", http_host); //DEBUG("REFERER %s!\n", http_referer); if (http_port) { *http_port = 0; http_port ++; } else { http_port = conn->sock->ssl?"443":"80"; } if (!tpsocket_parse_url(http_referer, &host, &port, NULL, &conn_type) || (!conn->sock->ssl != !(conn_type&TPSOCKET_TYPE_SSL)) || !strcasesame(http_host, host) || !strcasesame(http_port, port)) { check_result = false; } //DEBUG("SSL %d %d!\n", !!conn->sock->ssl , !!(conn_type&TPSOCKET_TYPE_SSL)); //DEBUG("HOST %s %s!\n", http_host, host); //DEBUG("PORT %s %s!\n", http_port, port); free(host); free(port); } free(http_referer); free(http_host); if (!check_result) { CDEBUG("REFERER CHECK FAILED!\n"); goto refresh; } } if (http_auth == TPHTTP_AUTH_BASIC) { DEBUG_CRED("CLIENT USE BASIC %s\n", auth_info.basic); authed = TPHTTP_AUTH_BASIC; list_for_each_entry(c, &server->credential, list) { DEBUG_CRED("CREDITIAL 0x%x '%s' '%s'\n", c->auth_type, c->param1, c->param2); if (c->auth_type == TPHTTP_AUTH_BASIC) { if (c->auth_cb(&auth_info, c->auth_type, c->username, c->password, c->auth_priv)) { authed |= TPHTTP_AUTH_OK; authed_c = c; DEBUG_CRED("BASIC OK\n", auth_info.basic); break; } } } session = tphttp_session_find_strict(server, cookie, authed); if (session && (authed & TPHTTP_AUTH_OK)) { session->credential = c; } } else if (http_auth == TPHTTP_AUTH_DIGEST) { DEBUG_CRED("CLIENT USE DIGEST\n"); authed = TPHTTP_AUTH_DIGEST; session = auth_info.nonce ? tphttp_session_find(server, auth_info.nonce, TPHTTP_AUTH_DIGEST) : NULL; if (!auth_info.algorithm) { DEBUG_CRED("algorithm not specified, use default \"MD5\"\n"); auth_info.algorithm = strdup("MD5"); } if (session && username && auth_info.digest && opaque && auth_info.realm && auth_info.nonce && auth_info.cnonce && auth_info.nc_s && (nc > session->nc) && strsame(auth_info.realm, session->realm) && strcasesame(auth_info.algorithm, session->algorithm)) { DEBUG_CRED("FOUND SESSION %p %s %s\n", session, opaque, session?session->token:""); list_for_each_entry(c, &server->credential, list) { DEBUG_CRED("USERNAME %s %s %s %s\n", username, c->username, opaque, session->token); if (c->auth_type == TPHTTP_AUTH_DIGEST && strsame(username, c->username) && strsame(opaque, session->token)) { if (c->auth_cb(&auth_info, c->auth_type, c->username, c->password, c->auth_priv)) { authed |= TPHTTP_AUTH_OK; session->credential = c; tphttp_session_set_authed(session); session->nc = nc; DEBUG_CRED("DIGEST OK\n"); break; } } } } else { if (session) { DEBUG_CRED("SESSION NOT FOUND %p %s %s\n", session, opaque, session?session->token:""); DEBUG_CRED("session->realm \"%s\"=\"%s\" username=%s session->algorithm %s=%s\n", auth_info.realm, session->realm, username, auth_info.algorithm,session->algorithm); DEBUG_CRED("nc %d>%d response=%s\n", nc, session->nc, auth_info.digest); } } if (session && (session->authed&TPHTTP_AUTH_DIGEST)) { goto refresh; } } else if (cookie && server->cookie_auth) { DEBUG_CRED("CLIENT WITH COOKIE:%s\n",cookie); session = tphttp_session_find(server, cookie, TPHTTP_AUTH_NONE); if (session) { authed = session->authed; if (token) { free(session->token); session->token = token; token = NULL; } } } else { } end: if (!session || (session->authed != authed)) { int server_auth = 0, count = 0; struct tphttp_credential *ipauthed = NULL; list_for_each_entry(c, &server->credential, list) { count ++; server_auth |= c->auth_type; if (c->auth_type == TPHTTP_AUTH_IPADDR && strsame(addr, c->ipaddr)) { ipauthed = c; if (session) { session->credential = ipauthed; tphttp_session_set_authed(session); DEBUG_CRED("IP ADDR AUTHED SESSION %p\n", session); goto refresh; } } } session = tphttp_session_new(server); if (session) { DEBUG_CRED("new SESSION %p\n", session); session->addr = strdup(addr); if (ipauthed) { tphttp_session_set_authed(session); session->authed = session->authed; session->credential = ipauthed; DEBUG_CRED("IP ADDR AUTHED SESSION %p\n", session); } else if ((server_auth & TPHTTP_AUTH_DIGEST) && (!(server_auth & TPHTTP_AUTH_BASIC) || !(http_auth & TPHTTP_AUTH_BASIC))) { int i = 0; char*p = NULL, *q = NULL; session->authed = TPHTTP_AUTH_DIGEST; session->qop = strdup(server->digest_qop ? server->digest_qop : "auth"); session->algorithm = strdup(server->digest_algorithm ? server->digest_algorithm : "MD5-sess"); session->token = malloc(33); session->token[32] = 0; tpsocket_hex_random(session->token, 32, 0); if (server->encrypt_type) { session->encrypt_type = strdup(server->encrypt_type); } DEBUG_CRED("TPHTTP_AUTH_DIGEST SESSION %p %s %s\n", session, session->cookie, session->token); } else if (server_auth & TPHTTP_AUTH_BASIC) { session->authed = TPHTTP_AUTH_BASIC; if (authed == (TPHTTP_AUTH_BASIC | TPHTTP_AUTH_OK)) { session->credential = authed_c; tphttp_session_set_authed(session); } DEBUG_CRED("TPHTTP_AUTH_BASIC SESSION %p\n", session); } else { session->authed = TPHTTP_AUTH_NONE; if (!count) { tphttp_session_set_authed(session); } DEBUG_CRED("TPHTTP_AUTH_NONE SESSION %p\n", session); session->token = token; token = NULL; } } } refresh: conn->session = session; if (session) { tphttp_session_refresh(session); } free(username); free(opaque); free(cookie); free(token); free(auth_info.basic); free(auth_info.digest); free(auth_info.realm); free(auth_info.nonce); free(auth_info.cnonce); free(auth_info.uri); free(auth_info.qop); free(auth_info.algorithm); free(auth_info.nc_s); return session; }
最新发布
10-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值