ホーム › Security.Authentication.Identity › SslGetExtensions
SslGetExtensions
関数TLSのClientHelloから指定したTLS拡張データを取得する。
シグネチャ
// SCHANNEL.dll
#include <windows.h>
HRESULT SslGetExtensions(
const BYTE* clientHello,
DWORD clientHelloByteSize,
SCH_EXTENSION_DATA* genericExtensions,
BYTE genericExtensionsCount,
DWORD* bytesToRead,
SchGetExtensionsOptions flags
);パラメーター
| 名前 | 型 | 方向 | 説明 |
|---|---|---|---|
| clientHello | BYTE* | in | 解析対象のTLS ClientHelloメッセージのバイト列へのポインタ。 |
| clientHelloByteSize | DWORD | in | clientHelloが指すデータのバイト長。 |
| genericExtensions | SCH_EXTENSION_DATA* | inout | 抽出した拡張情報を格納するSCH_EXTENSION_DATA配列へのポインタ。 |
| genericExtensionsCount | BYTE | in | genericExtensions配列の要素数(取得したい拡張の数)。 |
| bytesToRead | DWORD* | out | 解析に必要な読み取りバイト数を受け取るDWORDへのポインタ。 |
| flags | SchGetExtensionsOptions | in | 解析動作を制御するSchGetExtensionsOptions列挙値。 |
戻り値の型: HRESULT
各言語での呼び出し定義
// SCHANNEL.dll
#include <windows.h>
HRESULT SslGetExtensions(
const BYTE* clientHello,
DWORD clientHelloByteSize,
SCH_EXTENSION_DATA* genericExtensions,
BYTE genericExtensionsCount,
DWORD* bytesToRead,
SchGetExtensionsOptions flags
);[DllImport("SCHANNEL.dll", ExactSpelling = true)]
static extern int SslGetExtensions(
IntPtr clientHello, // BYTE*
uint clientHelloByteSize, // DWORD
IntPtr genericExtensions, // SCH_EXTENSION_DATA* in/out
byte genericExtensionsCount, // BYTE
out uint bytesToRead, // DWORD* out
int flags // SchGetExtensionsOptions
);<DllImport("SCHANNEL.dll", ExactSpelling:=True)>
Public Shared Function SslGetExtensions(
clientHello As IntPtr, ' BYTE*
clientHelloByteSize As UInteger, ' DWORD
genericExtensions As IntPtr, ' SCH_EXTENSION_DATA* in/out
genericExtensionsCount As Byte, ' BYTE
<Out> ByRef bytesToRead As UInteger, ' DWORD* out
flags As Integer ' SchGetExtensionsOptions
) As Integer
End Function' clientHello : BYTE*
' clientHelloByteSize : DWORD
' genericExtensions : SCH_EXTENSION_DATA* in/out
' genericExtensionsCount : BYTE
' bytesToRead : DWORD* out
' flags : SchGetExtensionsOptions
Declare PtrSafe Function SslGetExtensions Lib "schannel" ( _
ByVal clientHello As LongPtr, _
ByVal clientHelloByteSize As Long, _
ByVal genericExtensions As LongPtr, _
ByVal genericExtensionsCount As Byte, _
ByRef bytesToRead As Long, _
ByVal flags As Long) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。import ctypes
from ctypes import wintypes
SslGetExtensions = ctypes.windll.schannel.SslGetExtensions
SslGetExtensions.restype = ctypes.c_int
SslGetExtensions.argtypes = [
ctypes.POINTER(ctypes.c_ubyte), # clientHello : BYTE*
wintypes.DWORD, # clientHelloByteSize : DWORD
ctypes.c_void_p, # genericExtensions : SCH_EXTENSION_DATA* in/out
ctypes.c_ubyte, # genericExtensionsCount : BYTE
ctypes.POINTER(wintypes.DWORD), # bytesToRead : DWORD* out
ctypes.c_int, # flags : SchGetExtensionsOptions
]require 'fiddle'
require 'fiddle/import'
lib = Fiddle.dlopen('SCHANNEL.dll')
SslGetExtensions = Fiddle::Function.new(
lib['SslGetExtensions'],
[
Fiddle::TYPE_VOIDP, # clientHello : BYTE*
-Fiddle::TYPE_INT, # clientHelloByteSize : DWORD
Fiddle::TYPE_VOIDP, # genericExtensions : SCH_EXTENSION_DATA* in/out
-Fiddle::TYPE_CHAR, # genericExtensionsCount : BYTE
Fiddle::TYPE_VOIDP, # bytesToRead : DWORD* out
Fiddle::TYPE_INT, # flags : SchGetExtensionsOptions
],
Fiddle::TYPE_INT)#[link(name = "schannel")]
extern "system" {
fn SslGetExtensions(
clientHello: *const u8, // BYTE*
clientHelloByteSize: u32, // DWORD
genericExtensions: *mut SCH_EXTENSION_DATA, // SCH_EXTENSION_DATA* in/out
genericExtensionsCount: u8, // BYTE
bytesToRead: *mut u32, // DWORD* out
flags: i32 // SchGetExtensionsOptions
) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.$sig = @"
[DllImport("SCHANNEL.dll")]
public static extern int SslGetExtensions(IntPtr clientHello, uint clientHelloByteSize, IntPtr genericExtensions, byte genericExtensionsCount, out uint bytesToRead, int flags);
"@
$api = Add-Type -MemberDefinition $sig -Name 'SCHANNEL_SslGetExtensions' -Namespace Win32 -PassThru
# $api::SslGetExtensions(clientHello, clientHelloByteSize, genericExtensions, genericExtensionsCount, bytesToRead, flags)#uselib "SCHANNEL.dll"
#func global SslGetExtensions "SslGetExtensions" sptr, sptr, sptr, sptr, sptr, sptr
; SslGetExtensions varptr(clientHello), clientHelloByteSize, varptr(genericExtensions), genericExtensionsCount, varptr(bytesToRead), flags ; 戻り値は stat
; clientHello : BYTE* -> "sptr"
; clientHelloByteSize : DWORD -> "sptr"
; genericExtensions : SCH_EXTENSION_DATA* in/out -> "sptr"
; genericExtensionsCount : BYTE -> "sptr"
; bytesToRead : DWORD* out -> "sptr"
; flags : SchGetExtensionsOptions -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。出力引数:
#uselib "SCHANNEL.dll" #cfunc global SslGetExtensions "SslGetExtensions" var, int, var, int, var, int ; res = SslGetExtensions(clientHello, clientHelloByteSize, genericExtensions, genericExtensionsCount, bytesToRead, flags) ; clientHello : BYTE* -> "var" ; clientHelloByteSize : DWORD -> "int" ; genericExtensions : SCH_EXTENSION_DATA* in/out -> "var" ; genericExtensionsCount : BYTE -> "int" ; bytesToRead : DWORD* out -> "var" ; flags : SchGetExtensionsOptions -> "int" ; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。#uselib "SCHANNEL.dll" #cfunc global SslGetExtensions "SslGetExtensions" sptr, int, sptr, int, sptr, int ; res = SslGetExtensions(varptr(clientHello), clientHelloByteSize, varptr(genericExtensions), genericExtensionsCount, varptr(bytesToRead), flags) ; clientHello : BYTE* -> "sptr" ; clientHelloByteSize : DWORD -> "int" ; genericExtensions : SCH_EXTENSION_DATA* in/out -> "sptr" ; genericExtensionsCount : BYTE -> "int" ; bytesToRead : DWORD* out -> "sptr" ; flags : SchGetExtensionsOptions -> "int" ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。
出力引数:
; HRESULT SslGetExtensions(BYTE* clientHello, DWORD clientHelloByteSize, SCH_EXTENSION_DATA* genericExtensions, BYTE genericExtensionsCount, DWORD* bytesToRead, SchGetExtensionsOptions flags) #uselib "SCHANNEL.dll" #cfunc global SslGetExtensions "SslGetExtensions" var, int, var, int, var, int ; res = SslGetExtensions(clientHello, clientHelloByteSize, genericExtensions, genericExtensionsCount, bytesToRead, flags) ; clientHello : BYTE* -> "var" ; clientHelloByteSize : DWORD -> "int" ; genericExtensions : SCH_EXTENSION_DATA* in/out -> "var" ; genericExtensionsCount : BYTE -> "int" ; bytesToRead : DWORD* out -> "var" ; flags : SchGetExtensionsOptions -> "int" ; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。; HRESULT SslGetExtensions(BYTE* clientHello, DWORD clientHelloByteSize, SCH_EXTENSION_DATA* genericExtensions, BYTE genericExtensionsCount, DWORD* bytesToRead, SchGetExtensionsOptions flags) #uselib "SCHANNEL.dll" #cfunc global SslGetExtensions "SslGetExtensions" intptr, int, intptr, int, intptr, int ; res = SslGetExtensions(varptr(clientHello), clientHelloByteSize, varptr(genericExtensions), genericExtensionsCount, varptr(bytesToRead), flags) ; clientHello : BYTE* -> "intptr" ; clientHelloByteSize : DWORD -> "int" ; genericExtensions : SCH_EXTENSION_DATA* in/out -> "intptr" ; genericExtensionsCount : BYTE -> "int" ; bytesToRead : DWORD* out -> "intptr" ; flags : SchGetExtensionsOptions -> "int" ; ※出力/バッファ引数はポインタ方式(token=intptr / 呼び出しは varptr(変数))。
import (
"golang.org/x/sys/windows"
"unsafe"
)
var (
schannel = windows.NewLazySystemDLL("SCHANNEL.dll")
procSslGetExtensions = schannel.NewProc("SslGetExtensions")
)
// clientHello (BYTE*), clientHelloByteSize (DWORD), genericExtensions (SCH_EXTENSION_DATA* in/out), genericExtensionsCount (BYTE), bytesToRead (DWORD* out), flags (SchGetExtensionsOptions)
r1, _, err := procSslGetExtensions.Call(
uintptr(clientHello),
uintptr(clientHelloByteSize),
uintptr(genericExtensions),
uintptr(genericExtensionsCount),
uintptr(bytesToRead),
uintptr(flags),
)
_ = err // syscall.Errno (valid when the call sets last-error)
_ = r1 // HRESULTfunction SslGetExtensions(
clientHello: Pointer; // BYTE*
clientHelloByteSize: DWORD; // DWORD
genericExtensions: Pointer; // SCH_EXTENSION_DATA* in/out
genericExtensionsCount: Byte; // BYTE
bytesToRead: Pointer; // DWORD* out
flags: Integer // SchGetExtensionsOptions
): Integer; stdcall;
external 'SCHANNEL.dll' name 'SslGetExtensions';result := DllCall("SCHANNEL\SslGetExtensions"
, "Ptr", clientHello ; BYTE*
, "UInt", clientHelloByteSize ; DWORD
, "Ptr", genericExtensions ; SCH_EXTENSION_DATA* in/out
, "UChar", genericExtensionsCount ; BYTE
, "Ptr", bytesToRead ; DWORD* out
, "Int", flags ; SchGetExtensionsOptions
, "Int") ; return: HRESULT●SslGetExtensions(clientHello, clientHelloByteSize, genericExtensions, genericExtensionsCount, bytesToRead, flags) = DLL("SCHANNEL.dll", "int SslGetExtensions(void*, dword, void*, byte, void*, int)")
# 呼び出し: SslGetExtensions(clientHello, clientHelloByteSize, genericExtensions, genericExtensionsCount, bytesToRead, flags)
# clientHello : BYTE* -> "void*"
# clientHelloByteSize : DWORD -> "dword"
# genericExtensions : SCH_EXTENSION_DATA* in/out -> "void*"
# genericExtensionsCount : BYTE -> "byte"
# bytesToRead : DWORD* out -> "void*"
# flags : SchGetExtensionsOptions -> "int"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。const std = @import("std");
extern "schannel" fn SslGetExtensions(
clientHello: [*c]u8, // BYTE*
clientHelloByteSize: u32, // DWORD
genericExtensions: [*c]SCH_EXTENSION_DATA, // SCH_EXTENSION_DATA* in/out
genericExtensionsCount: u8, // BYTE
bytesToRead: [*c]u32, // DWORD* out
flags: i32 // SchGetExtensionsOptions
) callconv(std.os.windows.WINAPI) i32;proc SslGetExtensions(
clientHello: ptr uint8, # BYTE*
clientHelloByteSize: uint32, # DWORD
genericExtensions: ptr SCH_EXTENSION_DATA, # SCH_EXTENSION_DATA* in/out
genericExtensionsCount: uint8, # BYTE
bytesToRead: ptr uint32, # DWORD* out
flags: int32 # SchGetExtensionsOptions
): int32 {.importc: "SslGetExtensions", stdcall, dynlib: "SCHANNEL.dll".}pragma(lib, "schannel");
extern(Windows)
int SslGetExtensions(
ubyte* clientHello, // BYTE*
uint clientHelloByteSize, // DWORD
SCH_EXTENSION_DATA* genericExtensions, // SCH_EXTENSION_DATA* in/out
ubyte genericExtensionsCount, // BYTE
uint* bytesToRead, // DWORD* out
int flags // SchGetExtensionsOptions
);ccall((:SslGetExtensions, "SCHANNEL.dll"), stdcall, Int32,
(Ptr{UInt8}, UInt32, Ptr{SCH_EXTENSION_DATA}, UInt8, Ptr{UInt32}, Int32),
clientHello, clientHelloByteSize, genericExtensions, genericExtensionsCount, bytesToRead, flags)
# clientHello : BYTE* -> Ptr{UInt8}
# clientHelloByteSize : DWORD -> UInt32
# genericExtensions : SCH_EXTENSION_DATA* in/out -> Ptr{SCH_EXTENSION_DATA}
# genericExtensionsCount : BYTE -> UInt8
# bytesToRead : DWORD* out -> Ptr{UInt32}
# flags : SchGetExtensionsOptions -> Int32
# stdcall は 32bit のみ意味を持つ(x64 では無視)。local ffi = require("ffi")
ffi.cdef[[
int32_t SslGetExtensions(
uint8_t* clientHello,
uint32_t clientHelloByteSize,
void* genericExtensions,
uint8_t genericExtensionsCount,
uint32_t* bytesToRead,
int32_t flags);
]]
local schannel = ffi.load("schannel")
-- schannel.SslGetExtensions(clientHello, clientHelloByteSize, genericExtensions, genericExtensionsCount, bytesToRead, flags)
-- clientHello : BYTE*
-- clientHelloByteSize : DWORD
-- genericExtensions : SCH_EXTENSION_DATA* in/out
-- genericExtensionsCount : BYTE
-- bytesToRead : DWORD* out
-- flags : SchGetExtensionsOptions
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。const koffi = require('koffi');
const lib = koffi.load('SCHANNEL.dll');
const SslGetExtensions = lib.func('__stdcall', 'SslGetExtensions', 'int32_t', ['uint8_t *', 'uint32_t', 'void *', 'uint8_t', 'uint32_t *', 'int32_t']);
// SslGetExtensions(clientHello, clientHelloByteSize, genericExtensions, genericExtensionsCount, bytesToRead, flags)
// clientHello : BYTE* -> 'uint8_t *'
// clientHelloByteSize : DWORD -> 'uint32_t'
// genericExtensions : SCH_EXTENSION_DATA* in/out -> 'void *'
// genericExtensionsCount : BYTE -> 'uint8_t'
// bytesToRead : DWORD* out -> 'uint32_t *'
// flags : SchGetExtensionsOptions -> 'int32_t'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。const lib = Deno.dlopen("SCHANNEL.dll", {
SslGetExtensions: { parameters: ["pointer", "u32", "pointer", "u8", "pointer", "i32"], result: "i32" },
});
// lib.symbols.SslGetExtensions(clientHello, clientHelloByteSize, genericExtensions, genericExtensionsCount, bytesToRead, flags)
// clientHello : BYTE* -> "pointer"
// clientHelloByteSize : DWORD -> "u32"
// genericExtensions : SCH_EXTENSION_DATA* in/out -> "pointer"
// genericExtensionsCount : BYTE -> "u8"
// bytesToRead : DWORD* out -> "pointer"
// flags : SchGetExtensionsOptions -> "i32"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。<?php
$ffi = FFI::cdef(<<<C
int32_t SslGetExtensions(
uint8_t* clientHello,
uint32_t clientHelloByteSize,
void* genericExtensions,
uint8_t genericExtensionsCount,
uint32_t* bytesToRead,
int32_t flags);
C, "SCHANNEL.dll");
// $ffi->SslGetExtensions(clientHello, clientHelloByteSize, genericExtensions, genericExtensionsCount, bytesToRead, flags);
// clientHello : BYTE*
// clientHelloByteSize : DWORD
// genericExtensions : SCH_EXTENSION_DATA* in/out
// genericExtensionsCount : BYTE
// bytesToRead : DWORD* out
// flags : SchGetExtensionsOptions
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
public interface Schannel extends StdCallLibrary {
Schannel INSTANCE = Native.load("schannel", Schannel.class);
int SslGetExtensions(
byte[] clientHello, // BYTE*
int clientHelloByteSize, // DWORD
Pointer genericExtensions, // SCH_EXTENSION_DATA* in/out
byte genericExtensionsCount, // BYTE
IntByReference bytesToRead, // DWORD* out
int flags // SchGetExtensionsOptions
);
}@[Link("schannel")]
lib LibSCHANNEL
fun SslGetExtensions = SslGetExtensions(
clientHello : UInt8*, # BYTE*
clientHelloByteSize : UInt32, # DWORD
genericExtensions : SCH_EXTENSION_DATA*, # SCH_EXTENSION_DATA* in/out
genericExtensionsCount : UInt8, # BYTE
bytesToRead : UInt32*, # DWORD* out
flags : Int32 # SchGetExtensionsOptions
) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。import 'dart:ffi';
import 'package:ffi/ffi.dart';
typedef SslGetExtensionsNative = Int32 Function(Pointer<Uint8>, Uint32, Pointer<Void>, Uint8, Pointer<Uint32>, Int32);
typedef SslGetExtensionsDart = int Function(Pointer<Uint8>, int, Pointer<Void>, int, Pointer<Uint32>, int);
final SslGetExtensions = DynamicLibrary.open('SCHANNEL.dll')
.lookupFunction<SslGetExtensionsNative, SslGetExtensionsDart>('SslGetExtensions');
// clientHello : BYTE* -> Pointer<Uint8>
// clientHelloByteSize : DWORD -> Uint32
// genericExtensions : SCH_EXTENSION_DATA* in/out -> Pointer<Void>
// genericExtensionsCount : BYTE -> Uint8
// bytesToRead : DWORD* out -> Pointer<Uint32>
// flags : SchGetExtensionsOptions -> Int32
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。{$mode objfpc}{$H+}
function SslGetExtensions(
clientHello: Pointer; // BYTE*
clientHelloByteSize: DWORD; // DWORD
genericExtensions: Pointer; // SCH_EXTENSION_DATA* in/out
genericExtensionsCount: Byte; // BYTE
bytesToRead: Pointer; // DWORD* out
flags: Integer // SchGetExtensionsOptions
): Integer; stdcall;
external 'SCHANNEL.dll' name 'SslGetExtensions';import Foreign
import Foreign.C.Types
import Foreign.C.String
foreign import stdcall safe "SslGetExtensions"
c_SslGetExtensions :: Ptr Word8 -> Word32 -> Ptr () -> Word8 -> Ptr Word32 -> Int32 -> IO Int32
-- clientHello : BYTE* -> Ptr Word8
-- clientHelloByteSize : DWORD -> Word32
-- genericExtensions : SCH_EXTENSION_DATA* in/out -> Ptr ()
-- genericExtensionsCount : BYTE -> Word8
-- bytesToRead : DWORD* out -> Ptr Word32
-- flags : SchGetExtensionsOptions -> Int32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。open Ctypes
open Foreign
let sslgetextensions =
foreign "SslGetExtensions"
((ptr uint8_t) @-> uint32_t @-> (ptr void) @-> uint8_t @-> (ptr uint32_t) @-> int32_t @-> returning int32_t)
(* clientHello : BYTE* -> (ptr uint8_t) *)
(* clientHelloByteSize : DWORD -> uint32_t *)
(* genericExtensions : SCH_EXTENSION_DATA* in/out -> (ptr void) *)
(* genericExtensionsCount : BYTE -> uint8_t *)
(* bytesToRead : DWORD* out -> (ptr uint32_t) *)
(* flags : SchGetExtensionsOptions -> int32_t *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)(cffi:define-foreign-library schannel (t "SCHANNEL.dll"))
(cffi:use-foreign-library schannel)
(cffi:defcfun ("SslGetExtensions" ssl-get-extensions :convention :stdcall) :int32
(client-hello :pointer) ; BYTE*
(client-hello-byte-size :uint32) ; DWORD
(generic-extensions :pointer) ; SCH_EXTENSION_DATA* in/out
(generic-extensions-count :uint8) ; BYTE
(bytes-to-read :pointer) ; DWORD* out
(flags :int32)) ; SchGetExtensionsOptions
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。use Win32::API;
my $SslGetExtensions = Win32::API::More->new('SCHANNEL',
'int SslGetExtensions(LPVOID clientHello, DWORD clientHelloByteSize, LPVOID genericExtensions, BYTE genericExtensionsCount, LPVOID bytesToRead, int flags)');
# my $ret = $SslGetExtensions->Call($clientHello, $clientHelloByteSize, $genericExtensions, $genericExtensionsCount, $bytesToRead, $flags);
# clientHello : BYTE* -> LPVOID
# clientHelloByteSize : DWORD -> DWORD
# genericExtensions : SCH_EXTENSION_DATA* in/out -> LPVOID
# genericExtensionsCount : BYTE -> BYTE
# bytesToRead : DWORD* out -> LPVOID
# flags : SchGetExtensionsOptions -> int
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。