WinInetでSSL通信 – プログラミング – Home

通知
すべてクリア

[解決済] WinInetでSSL通信


田中さん
 田中さん
(@田中さん)
ゲスト
結合: 19年前
投稿: 49
Topic starter  

開発環境はVisualC.NET+SDKです。

WinInetを使ってWebクライアントを作っています。

httpsページを取得しようとしていますが、InternetConnect関数で失敗しています。
どのあたりに間違いがありそうか探しています。何かヒントはありませんか?

コードは以下のように作りました。
void GetDataByInetSSL(void){
HINTERNET hOpen;
HINTERNET hConn;
HINTERNET hInternet;
DWORD dwReadSize;
DWORD dwSize;
HGLOBAL hGBuff;
LPSTR lpszBuff;

char szScheme[256], szServerName[256], szUserName[256], szPassword
[256],szObjectName[256], szExtraInfo[256];
URL_COMPONENTSA UrlComponents;

UrlComponents.dwStructSize = sizeof(URL_COMPONENTSA); //コンポーネント
のサイズ確保
UrlComponents.nScheme = INTERNET_SCHEME_DEFAULT;
UrlComponents.lpszScheme = szScheme; // Schemeの領域
の確保
UrlComponents.dwSchemeLength = sizeof(szScheme);
UrlComponents.lpszHostName = szServerName; // HostNameの領域の確保
UrlComponents.dwHostNameLength = sizeof(szServerName);
UrlComponents.lpszUserName = szUserName; // UserNameの領域の確保
UrlComponents.dwUserNameLength = sizeof(szUserName);
UrlComponents.lpszPassword = szPassword; // Passwordの領域の確保
UrlComponents.dwPasswordLength = sizeof(szPassword);
UrlComponents.lpszUrlPath = szObjectName; // UrlPathの領域の確保
UrlComponents.dwUrlPathLength = sizeof(szObjectName);
UrlComponents.lpszExtraInfo = szExtraInfo; // ExtraInfoの領域の確保
UrlComponents.dwExtraInfoLength = sizeof(szExtraInfo);

InternetCrackUrl(inifiles.url,sizeof
(inifiles.url),ICU_DECODE,&UrlComponents);

hOpen=InternetOpen(INET PROGRAM,
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
if(hOpen==false){
DISP(Internet関数に失敗しました);
return;
}

hConn=InternetConnect(hOpen, //Openハンドル
UrlComponents.lpszHostName, //サーバー名
UrlComponents.nPort, //ポート
UrlComponents.lpszUserName, //ユーザー名
UrlComponents.lpszPassword, //ユーザーパスワード
UrlComponents.nScheme, //サービス
0,
0);
if(hConn==false){
InternetCloseHandle(hOpen);
DISP(InternetConnect関数に失敗しました);
return;
}

hInternet=HttpOpenRequest(hConn, //接続
GET, //手法
UrlComponents.lpszUrlPath, //ページ名
HTTP_VERSION, //Version
NULL,
NULL,
INTERNET_FLAG_SECURE, //flags
0);

//読み込みバッファ確保
InternetQueryDataAvailable(hInternet,&dwReadSize,0,0);
hGBuff=GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD,dwReadSize+1);
lpszBuff=(LPSTR)GlobalLock(hGBuff);

while(true){
InternetReadFile(hInternet,lpszBuff,dwReadSize,&dwSize);
if(dwSize==0){
break;
}
lpszBuff[dwSize]='\0';
DISP(lpszBuff);
}
GlobalUnlock(hGBuff);
GlobalFree(hGBuff);
InternetCloseHandle(hInternet);
InternetCloseHandle(hConn);
InternetCloseHandle(hOpen);
}


引用未解決
トピックタグ
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

とりあえず、GetLastError や InternetGetLastResponseInfo で
エラー理由を調べてみるのがよいと思います。


返信引用
田中さん
 田中さん
(@田中さん)
ゲスト
結合: 19年前
投稿: 49
Topic starter  

すみません。ちょっと出張中でテストが出来ずレス遅くなりました。

GetLastError()ではエラーコードが87が帰ってきました。
InternetGetLastResponseInfoではうまくエラーメッセージが帰って来ませんでした。

サーバーは自作サーバーでApache+Opensslです。
リダイレクトなどの処理はしていませんので認証、認証の前準備がダメなのだと思いま
す。

どこかに糸口はありませんでしょうか?


返信引用
通りすがり
 通りすがり
(@通りすがり)
ゲスト
結合: 24年前
投稿: 92
 

Code Description Name
87 The parameter is incorrect. ERROR_INVALID_PARAMETER

InternetCrackUrlの成否判定してないみたいだけど

パラメータエラーなんだから
inifiles.urlに入ってる文字列が変とか、
inifiles.urlがポインタになってsizeofが…とか
そういう理由でInternetCrackUrlで分解失敗してて
InternetConnectも失敗してるとかじゃない?


返信引用
通りすがり
 通りすがり
(@通りすがり)
ゲスト
結合: 24年前
投稿: 92
 

ん?
InternetConnectの6番目のパラメータ間違ってるじゃん。
ここにいれるのはINTERNET_SCHEME~じゃなくてINTERNET_SERVICEだよ


返信引用
通りすがり
 通りすがり
(@通りすがり)
ゲスト
結合: 24年前
投稿: 92
 

途中で送っちゃった

で、
INTERNET_SCHEME~にはHTTPSの3ふがあるけど、
INTERNET_SERVICE~には無いからパラメータエラーになってるのかと。


返信引用
田中さん
 田中さん
(@田中さん)
ゲスト
結合: 19年前
投稿: 49
Topic starter  

ありがとうございます。上記のようにInternetConnectの関数を

hConn=InternetConnect(hOpen, //Openハンドル
UrlComponents.lpszHostName, //サーバー名
UrlComponents.nPort, //ポート
UrlComponents.lpszUserName, //ユーザー名
UrlComponents.lpszPassword, //ユーザーパスワード
INTERNET_SERVICE_HTTP, //サービス
0,
0);
とすると先に進めるようになりました。

ただこの後に、また問題が出てきたのですが、この後の処理を以下のようにしました。
//---ここから
hInternet=HttpOpenRequest
(hConn,GET,UrlComponents.lpszUrlPath,HTTP_VERSION,",NULL,INTERNET_FLAG_SECURE
,0);

//作成したHTTP要求を発行
bRet=HttpSendRequest(hInternet,NULL, 0,NULL,0);
//----こきまで

この処理でHttpSendRequestが「不明な認証局の認証証」というエラーを返します。
自作のSSLサーバーなのでエラーが出るのは当然なのですがそれが回避できません。

試しにSSLで構築してある一般のサーバーにアクセスした場合は普通にページが取得でき
ました(IEで認証証をGETした後)。

不明な認証局を使う場合のフラッグの設定が悪いのか?と思っています。
もしくはHttpSendRequestに何かオプションを付ける必要があるのでしょうか?


返信引用
田中さん
 田中さん
(@田中さん)
ゲスト
結合: 19年前
投稿: 49
Topic starter  

すみません。
認証証の質問については文章を見直すとまとまっていないし、
最初のタイトルからは違った内容になっているので
改めて別の質問として発言を立てます。
一旦この質問は解決済みとします。


返信引用
まりのちゃん
 まりのちゃん
(@まりのちゃん)
ゲスト
結合: 18年前
投稿: 16
 

新スレがたたないようなので
一応私が実装したものを参考に書いておきます。

>この処理でHttpSendRequestが「不明な認証局の認証証」というエラーを返します。
>自作のSSLサーバーなのでエラーが出るのは当然なのですがそれが回避できません。

正式な認証サーバでないとHttpOpenRequestでは失敗するようです。
なので下記ロジックのようにHttpOpenRequest後にエラーを無視させる
フラグをsetoptionで設定します。
dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
dwFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
dwFlags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
dwFlags |= SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTP;
dwFlags |= SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTPS;
これでHttpSendRequestがいけると思います。

あとHttpSendRequestなんですが、
ヘッダContent-Type: application/x-www-form-urlencoded
を設定しないとリクエストが飛びません。
なので以下を参考にしてみてください。

hHttpRequest = HttpOpenRequest(
hHttpSession,
POST,
requestFile,
NULL,
NULL,
NULL,
INTERNET_FLAG_SECURE,
0);
if( hHttpRequest == NULL)
{
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hInternet);
return false;
}

DWORD dwError = 0;
DWORD dwFlags;
DWORD dwBuffLen = sizeof(dwFlags);

ret = InternetQueryOption (hHttpRequest, INTERNET_OPTION_SECURITY_FLAGS,
(LPVOID)&dwFlags, &dwBuffLen);
if(ret == FALSE)
{
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hInternet);
return false;
}

dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
dwFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
dwFlags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
dwFlags |= SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTP;
dwFlags |= SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTPS;

ret = InternetSetOption (hHttpRequest, INTERNET_OPTION_SECURITY_FLAGS,
&dwFlags,
sizeof (dwFlags) );
if(ret == FALSE)
{
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hInternet);
return false;
}

CString sHeader;
CString sOption;
char Opt[512];

// ヘッダー生成
sHeader = Content-Type: application/x-www-form-urlencoded;

if(!HttpSendRequest(hHttpRequest, sHeader, sHeader.GetLength(),
(LPVOID)&TEST=777, sizeof(&TEST=777)))
{
InternetCloseHandle(hHttpRequest);
InternetCloseHandle(hHttpSession);
InternetCloseHandle(hInternet);
return false;
}


返信引用
田中さん
 田中さん
(@田中さん)
ゲスト
結合: 19年前
投稿: 49
Topic starter  

まりのちゃんさんありがとうございます
コードを参考にして以下のようにしたら解決しました。
まりのちゃんさんのコードとの違いはリダイレクトの処理とPOSTの処理です。
エラー処理はGoto文で処理してるので省略させて頂いてます。

//---コードここから

//リクエスト作成
hInternet=HttpOpenRequest
(hConn,GET,UrlComponents.lpszUrlPath,HTTP_VERSION,",NULL,INTERNET_FLAG_SECURE
,0);
if(!hInternet){
エラー処理・・・
}

//オプションを設定する
DWORD dwFlags;
DWORD dwFlagsLen=sizeof(dwFlags);
bRet=InternetQueryOption(hInternet, INTERNET_OPTION_SECURITY_FLAGS,
(LPVOID)&dwFlags, &dwFlagsLen);
if(!bRet){
エラー処理・・・
}
dwFlags|=SECURITY_FLAG_IGNORE_UNKNOWN_CA;
dwFlags|=SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
dwFlags|=SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
bRet=InternetSetOption(hInternet,INTERNET_OPTION_SECURITY_FLAGS,
&dwFlags, sizeof(dwFlags));
if(!bRet){
エラー処理・・・
}

//作成したHTTP要求を発行
bRet=HttpSendRequest(hInternet, NULL,0,NULL,0);
if(bRet==FALSE){
エラー処理・・・
}

//---ここまで

ありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました