アクセス権のチェック方法について
- 指定したユーザが指定ファイルを読むことができるかをチェックするツールを作成したいです。
- LogonUser、ImpersonateLoggedOnUserを使用してユーザの偽装をし、CreateFileでファイルを開けば良いです。
- 実行するとすべてのファイルがCreateFileに成功してしまいます。ファイルの読み取り権限が無いと思っていましたが、違うのでしょうか?
- ベストアンサー
アクセス権のチェック方法について
あるフォルダ以下に、ユーザ毎にアクセス権が設定されたファイルがあり、指定したユーザが指定ファイルを読むことができるかをチェックするツールを作りたいと考えています。 APIを見ていて、LogonUser、ImpersonateLoggedOnUserを使ってチェックするユーザで偽装し、CreateFileでチェックするファイルを開けばよいかと思い、下記のようなコードを試しました。 ----- HANDLE hToken = NULL; HANDLE hFile = NULL; PTSTR pszUserName = "testuser"; PTSTR pszDomainName = "." PTSTR pszPassword = "testuser"; PTSTR pszFilePath = "C:\\test\\dir01\\001.txt"; try { { if (!LogonUser(pszUserName, pszDomainName, pszPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken)) { printf("error:%d\n",GetLastError()); goto leave; } hFile = CreateFile(pszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, SECURITY_SQOS_PRESENT | SECURITY_EFFECTIVE_ONLY, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("error2:%d\n",GetLastError()); } else { printf("OK\n"); } } } leave:; } catch(...) {} ----- 実行するとLogonUser、ImpersonateLoggedOnUserは成功しているようですが、セキュリティの有無にかかわらずすべてのファイルがCreateFileに成功してしまいます。 読み取り権限が無いファイルに対してはCreateFileは失敗すると思っていましたが違うのでしょうか? それとも、セキュリティをチェックする方法として根本的に間違っています?? 情報をお待ちしております。 環境は以下の通りです。 Win2000 SP4 VisualStudio6(VC++)
- tetsu_2005
- お礼率25% (1/4)
- C・C++・C#
- 回答数3
- ありがとう数1
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
ファイル不存在時の件ですが、こちらではファイル不存在時にはCreateFileでエラーとなりGetLastError()が2(ERROR_FILE_NOT_FOUND)を返しています。 メイン部分は以下のとおりです、ご質問の内容とほぼ1対1に対応しているので、動作が異なることはないと思うのですが・・・ HANDLE hToken = NULL; HANDLE hFile = NULL; PCSTR pszUserName = m_sUser; PCSTR pszDomainName = "."; PCSTR pszPassword = m_sPassword; PCSTR pszFilePath = m_sFilename; try { do { if (LogonUser(pszUserName, pszDomainName, pszPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken)) { if (ImpersonateLoggedOnUser(hToken)) { hFile = CreateFile(pszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, SECURITY_SQOS_PRESENT | SECURITY_EFFECTIVE_ONLY, NULL); if (!RevertToSelf()) { MessageBox("RevertToSelf() failed"); } if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); MessageBox("OK"); break; } } } CString s; s.Format("error:%d\n",GetLastError()); MessageBox(s); } while (0); } catch(...) { } なお、テストにはWindows 2000 Workstationを使用していますが、Windows XP Professionalでも同様の結果です。
その他の回答 (2)
- xcrOSgS2wY
- ベストアンサー率50% (1006/1985)
例示されているコードを元にテストプログラムを作成し試したところ、ちゃんとLogonUserしたユーザの読み取り権限に応じてCreateFileが成功/失敗しました。 テストに用いたファイルの読み取り権限の設定が誤っている(Everyoneに読み取り権限が設定されている等)ということはありませんか。
補足
回答ありがとうございます。 pszFilePathに存在しないファイルを指定していたのが原因でした。 存在するファイルを指定するとユーザの読み取り権限に応じて正しく動作しました。 しかし、CreateFileの引数でOPEN_EXISTINGを指定するとファイルが存在しない場合は関数が失敗する、とあるのに成功しているのはなぜなのでしょうか??
- xcrOSgS2wY
- ベストアンサー率50% (1006/1985)
「LogonUser、ImpersonateLoggedOnUserを使って」とあるのですが、コードの中にImpersonateLoggedOnUserがありません。 CreateFileの前にImpersonateLoggedOnUserを実行しておかないとツール実行時のユーザ権限のままになりますから、開発者権限でツールを実行している場合、CreateFileは(たいていの場合に)成功してしまうかと思います。
補足
回答ありがとうございます。 失礼しました、サンプルにImpersonateLoggedOnUserが抜けていました。 LogonUserで取得したハンドルをImpersonateLoggedOnUserに渡しています。 ----- ・・・ if (!LogonUser(pszUserName, pszDomainName, pszPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken)) { printf("error:%d\n",GetLastError()); goto leave; } ImpersonateLoggedOnUser(hToken); hFile = CreateFile(pszFilePath, ・・・ -----
関連するQ&A
- 【C言語】引数にファイルパスを送りたい
DLLで外部のファイルサイズを得る関数を作っています。 C言語は書きながら覚えていこうとしているのですが、 どうしても分からない点がありました。 ソースをここに正しく書ける自信がないので日本語を含めて大体で書きます。 いろいろなサイトのコピペです。 double __stdcall filesize(){ HANDLE hFile; DWORD size; hFile = CreateFile( _T(絶対パス, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); size = GetFileSize( hFile, NULL ); CloseHandle( hFile ); return(size); } このような感じで書いていて最後にretuenでファイルサイズを正しく得ることができました。 この絶対パスは環境によって変わるので引数にしようと考えました。 そしてfilesize()の中にどのように記述すればいいかで躓いています。 filesize(絶対パス){ char pass[] = "絶対パス"; hFile = CreateFile( _T(pass, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); こんな感じで書ければいいのですがC言語はポインタや文字列の扱いが難しいですね。 初歩的なことで申し訳ありませんがよろしくお願いします。
- 締切済み
- C・C++・C#
- exeファイルにドラッグすることで動作するプログラム再質問
前回、exeファイルにドラッグすることで動作するプログラムというタイトルで質問したものです。いといろやっていたら上手くいったと勘違いし、質問を締め切ってしまいました。実は上手くいっておらず、再度質問させていただきます。お手数をお掛けし申し訳ございませんが宜しくお願い申し上げます。 現在上手くいかないプログラムは以下のようなものです(具体的処理は省いています) #include <windows.h> #include <tchar.h> int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){ HANDLE hfile; hfile = CreateFile(lpCmdLine,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,NULL); if(hfile == INVALID_HANDLE_VALUE){ MessageBox(NULL,_T("error"),NULL,MB_OK); return false; } //ここで処理をします(今回は省略させていただきました) return 0; } このプログラムのexeファイルのアイコンにデータファイルをドラッグし、処理を行いたいのですが、データファイル名に日本語が含まれると hfile が INVALID_HANDLE_VALUEとなります。 データファイル名が英字のみの場合は上手くいきます。文字セットはUnicode文字セットを使用しています。 どなたかご教授お願い申し上げます。
- 締切済み
- C・C++・C#
- いやーマイクロソフトには苦労します
メモ帳で空のファイルx.txtを作り これをGetAttributeでディレクトリかどうかを検査すると x.txtはディレクトリとみなされてしまいます 今x.txtがディレクトリだと動作が異常になる プログラムを作っていたので困っています そこでx.txtを排除するためにサイズを検査して0ならば 処理をしないようにしようと思ったのですが サイズを調べるのに void DispFileSize() { HANDLE hFile; DWORD FileSizeLow, FileSizeHigh; hFile = CreateFile( "\\command.com", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); FileSizeLow = GetFileSize(hFile, &FileSizeHigh); printf("ファイルサイズ: %ud*2^32 + %ud\n", FileSizeHigh, FileSizeLow); CloseHandle(hFile); } などいいう馬鹿らしい処理をしなければなりません しかもこれはディレクトリに適用するものではないのでうまくいくかどうか・・・ ファイルサイズを出すのに簡単にする方法はないのでしょうか? しかしAPIはやたら引数が多いしわけのわからない定数をいっぱい使いますね 泣きたくなります 開発者に問題があるのでしょうね
- ベストアンサー
- C・C++・C#
- ReadFileの読み込みエラーについて
こんばんは Win32 APIでプログラミングをやっているのですが、そのAPIの中でReadFileというものがありますよね? この関数でエラー値が出力され、第二引数としてBITMAPINFO構造体に格納するはずの値がそのままです。 以下に一部ソースを載せます BOOL Cell_Init( HINSTANCE hInstance ) { BITMAPINFO bmi2; HANDLE hFile; DWORD dwBytes; // 作成するビットマップの情報を設定する BITMAPFILEHEADER bmpFileHeader; BITMAPINFO bmi; // ビットマップのハンドルと、作成したバッファの先頭アドレスを取得 void* pImage; HBITMAP hBitmap; // デスクトップのDCを得る HDC tmpDC = GetDC(GetDesktopWindow() ); // HBITMAPにHDCを結びつける g_hdc_cell = CreateCompatibleDC( tmpDC ); DWORD er; hFile = CreateFile("cointos.bmp", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); er = GetLastError(); if(hFile == INVALID_HANDLE_VALUE) return 0; ReadFile(hFile, &bmpFileHeader, sizeof(BITMAPFILEHEADER), &dwBytes, NULL); er = GetLastError(); if(bmpFileHeader.bfType != 0x4D42) { MessageBox(NULL, TEXT("This is not a bitmap file"), NULL, MB_OK); return FALSE; } //ここでbmi2に格納される値が格納されていない(そのためでかい値のまま) そのためCreateDIBSectionではエラーを起こす ReadFile(hFile, &bmi2, bmpFileHeader.bfOffBits - dwBytes, &dwBytes, NULL); er = GetLastError(); // ここの部分でエラー値998が出ます hBitmap = CreateDIBSection(tmpDC, &bmi2, DIB_RGB_COLORS, (LPVOID*)&pImage, NULL, 0); ReadFile(hFile,pImage, bmpFileHeader.bfSize - bmpFileHeader.bfOffBits, &dwBytes, NULL); SelectObject( g_hdc_cell, hBitmap ); CloseHandle(hFile); ReleaseDC(GetDesktopWindow(), tmpDC); return TRUE; } なぜこうなるんでしょうか? bmi2はBITMAPINFO構造体でローカルで宣言しています。これがポインタだと大丈夫なんですが なぜ変数ではダメなのか分かりません。 あらかじめ確保されているスタック領域の容量限界でも ないと思うのですが。 分かる方がいらっしゃったらよろしくお願いします。 開発環境はVS.2005 です。
- ベストアンサー
- C・C++・C#
- CreateFileしてからtruncate
ファイルデータを置換するプログラムを作っています。 短い文字に置換すると、ファイルサイズは小さくなります。 ところが、今のソースではファイルサイズ小さくなりません。 「abcdefg」のテスト中の「cde」を「H」に置換すると 「abHfgxx」になってしまいます。 ・hfile = CreateFile("test.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ・読む ・置換 ・上書き ・CloseHandle(hfile); というステップです。 ・読む の直後に、text.txtを0バイトにしたいんですが、 hfileを閉じないで、Perlのtruncateのようなことはできませんか?
- ベストアンサー
- C・C++・C#
- WinInetのInternetOpenUrl関数が正常に動作しない。
ネットワーク上のHTMLソースを取得しようとしています。InternetOpenUrl関数が動作せず、常にNULLが返ってきます。 環境は、WindowsXP、WindowsCE Platform Builder です。 void Get_HTML(){ HINTERNET hInternet; HINTERNET hFile; char Buff[1000]; DWORD ReadSize; BOOL bResult; //WinInetの初期化 char *agent ="WININET Sample Program"; hInternet = InternetOpen( (LPCWSTR)agent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 ); if( hInternet == NULL ){ printf("InternetOpen Error \n"); } //ネット接続チェック if( InternetAttemptConnect(0) != ERROR_SUCCESS { printf("インターネットに接続できません。\n"); } else{ printf("インターネットに接続できる\n"); } //URLオープン char open_url="http://www.sample.com/sam1.html"; hFile = InternetOpenUrl( hInternet, (LPCWSTR)open_url, NULL, 0, INTERNET_FLAG_RELOAD, 0 ); printf("%s",(LPCWSTR)open_url); if( hFile == NULL ){ printf(" InternetOpenUrl ERROR \n"); } } InternetOpenUrl関数の戻り値がNULLになりReadを することが出来ません。 解決方法よろしくお願い致します。
- ベストアンサー
- C・C++・C#
- 二次元的な(?)文字列から指定した箇所の数を取り出す方法を教えてください
はじめまして。 C++を勉強している途中なのですが、興味本位でwin32apiに手を出してみたのですが、文字列について混乱中です。 http://www.geocities.jp/ky_webid/win32c/051.htmlの使用例を参考にして、テキストファイルtext.txtから文字を抽出し、MessageBoxで表示できるようになりました。 使用例というのは、↓です。 HANDLE hFile; // ファイルを開く。ReadFile()が目的なのでGENERIC_READ指定が必須 hFile = CreateFile( _T("test.dat"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile != INVALID_HANDLE_VALUE ) // 本当に開くことができたか { TCHAR buf[256]; DWORD readsize; // 使わないとしても、読み取ったサイズは受け取らなくてはならない // bufに読み込んで、結果をメッセージボックスに表示 ReadFile( hFile, buf, sizeof(buf), &readsize, NULL ); buf[readsize] = _T('\0'); // 末尾に'\0'が無いので付加 MessageBox( hWnd, buf, _T("結果"), MB_OK ); // 最後に忘れずにファイルハンドルを閉じる CloseHandle( hFile ); } テキストファイルtext.txtの中身は、↓のようになっています。 1 2 aui 2 4 sd 6 7 db 2 1 cx ですので、MessageBoxでも、↑のように表示されたのを確認しました。 bufの中に↑の数字と文字が代入されているということなのでしょうが、たとえば4を指定したり、dbを指定したりと、一つずつ抽出する方法がわかりません。 配列みたいにbuf[1][1]と書いてみても、「int型はcharに変換できない」といった感じのエラーが表示されるだけでした。 この文字列bufにある文字や数字を一つずつ抽出する方法を教えてください。
- 締切済み
- C・C++・C#
- 実行時にエラーが出ます(;。;)
hFile = CreateFile("1.txt",GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL); この文章で実行時エラーが出ます。初心者なのでよろしくお願いします。 C言語です。
- ベストアンサー
- C・C++・C#
- WinAPIでのファイル操作について教えて下さい。
現在参考書やwebサイトと参考にWindowsプログラミングを学んでいます。 下記のサイトにあるファイル作成のソースをコンパイルして実行したのですが http://wisdom.sakura.ne.jp/system/winapi/win32/win111.html #include <windows.h> int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance , PSTR lpCmdLine , int nCmdShow) { HANDLE hFile; hFile = CreateFile( lpCmdLine , GENERIC_READ , 0 , NULL , CREATE_NEW , FILE_ATTRIBUTE_NORMAL , NULL ); if (hFile == INVALID_HANDLE_VALUE) { MessageBox( NULL , TEXT("ファイルを作成できません") , TEXT("エラー") , MB_OK ); return 1; } CloseHandle(hFile); return 0; } コンパイルは成功するのですが実行すると必ずエラーになります。 他のソースも同様にファイル操作に失敗した場合の表示が行われます。 自分が持っている参考書にはファイル操作についてあまり詳しく書かれていないので他のソースも試せません。 どなたか教えて下さいよろしくお願いします。
- ベストアンサー
- C・C++・C#
- NetBIOS名のエラー
WTSOpenQuerySessionInformationを使うとき、 プログラムを動かすPCのNetBIOS名を指定するので あればNULLでよいとあったので、今日1日やってみたのですが存在しないトークンを参照しました。となります 参照方法が調べてもわからないためわかるかた アドバイスいただけるとありがたいです #include<stdio.h> #include<windows.h> #include<wtsapi32.h> #include<process.h> int main(){ /*ハンドルをオープン*/ char name; char *p; HANDLE handle; BOOL wts; DWORD error; LPVOID lpMsgBuf; LPTSTR ppBuffer; DWORD pBytesReturned; name=NULL; /*NULLを指定するとプログラムを動かしているPCを指定できる*/ p=name; printf("%p[name]\n",&name); printf("name=%p\n",name); handle =WTSOpenServer((LPTSTR)&p); /*サーバーハンドルを取得します*/ printf("handle=%p\n",handle); error=GetLastError(); printf("errorコード=%d\n",error); /*ハンドルOPENのエラーメッセージを取得してメッセージBOXに表示してます*/ FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), AKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf,0,NULL); MessageBox(NULL,(LPCTSTR)lpMsgBuf,"Error",MB_OK | MB_ICONINFORMATION); /*バッファの開放*/ LocalFree(lpMsgBuf); /*セッション情報の取得*/ wts = WTSQuerySessionInformation( (HANDLE)&p, WTS_CURRENT_SESSION, WTSConnectState, &ppBuffer, &pBytesReturned ); printf("%p[ppBuffer]\n%p[pBytesReturned]\n",&ppBuffer,&pBytesReturned); return 0; }
- ベストアンサー
- C・C++・C#
お礼
私の環境では、提示いただいたサンプルでも不在ファイル指定でCreateFileが通ってしまいますが、別のPCで試したところ、不在ファイル指定でGetLastError()で2が返ってきました。 特権の設定で違いがあるのかもしれませんので、私のPCと正常動作しているPCを見比べようと思います。 ありがとうございました。