編集の要約なし |
|||
| (同じ利用者による、間の7版が非表示) | |||
| 1行目: | 1行目: | ||
== 概要 == | == 概要 == | ||
ユーザ情報とグループ情報は、システムのセキュリティと権限管理の基盤となる重要な要素である。<br> | |||
<br> | |||
Linuxにおけるユーザ情報とグループ情報の基本的な構造、保存場所、関連するファイル、管理コマンド等の情報は、<br> | |||
システム管理、セキュリティ設定、アプリケーション開発など、様々な場面で重要になる。<br> | |||
<br> | |||
特に、ユーザ認証、アクセス制御、ファイル所有権の管理等のタスクを行う場合に、これらの概念の理解が不可欠である。<br> | |||
<br><br> | |||
== ユーザ情報 == | |||
==== ユーザアカウント ==== | |||
各ユーザは、一意のユーザ名とユーザID (UID) を持つ。<br> | |||
<br> | |||
UIDの値が0の場合は特別であり、rootユーザ (スーパーユーザ) に割り当てられる。<br> | |||
通常のユーザアカウントは、UIDの値が1000から始まる。(システムによって異なる場合がある)<br> | |||
<br> | |||
==== /etc/passwdファイル ==== | |||
ユーザアカウント情報を格納する主要なファイルである。<br> | |||
<br> | |||
各行が1つのユーザアカウントを表しており、以下に示す形式で情報が記録されている。<br> | |||
<ユーザ名>:<パスワード>:<UID>:<GID>:<GECOS>:<ホームディレクトリ>:<シェル> | |||
<br> | |||
* ユーザ名 | |||
*: ログイン名 | |||
* パスワード | |||
*: 暗号化されたパスワード (通常は'x'で、実際のパスワードは/etc/shadowに保存されている) | |||
* UID | |||
*: ユーザID | |||
* GID | |||
*: プライマリグループID | |||
* GECOS | |||
*: ユーザのフルネーム等の追加情報 | |||
* ホームディレクトリ | |||
*: ユーザのホームディレクトリ | |||
* シェル | |||
*: ログイン時に使用されるシェル | |||
<br> | |||
==== /etc/shadowファイル ==== | |||
ユーザパスワードの暗号化された情報を格納する。<br> | |||
<br> | |||
セキュリティ上の理由から、rootユーザのみがアクセス可能である。<br> | |||
パスワードの有効期限や変更履歴などの情報も含まれている。<br> | |||
<br><br> | |||
== グループ情報 == | |||
==== グループ ==== | |||
ユーザをカテゴリ分けしており、ファイルやリソースへのアクセス権を管理するために使用される。<br> | |||
各グループは一意のグループ名とグループID (GID) を持つ。<br> | |||
<br> | |||
==== /etc/groupファイル ==== | |||
グループ情報を格納する主要なファイルである。<br> | |||
<br> | |||
各行が1つのグループを表しており、以下に示す形式で情報が記録されている。<br> | |||
<グループ名>:<パスワード>:<GID>:<ユーザリスト> | |||
<br> | |||
* グループ名 | |||
*: グループ名が表示されている。 | |||
* パスワード | |||
*: グループパスワード (通常は使用されず、'x'が表示されている) | |||
* GID | |||
*: グループID | |||
* ユーザリスト | |||
*: グループに所属する追加ユーザのリスト (カンマ区切り) | |||
<br> | |||
==== プライマリグループとセカンダリグループ ==== | |||
プライマリグループとは、ユーザが作成したファイルのデフォルトグループ所有権である。<br> | |||
セカンダリグループとは、ユーザが追加で所属するグループである。<br> | |||
<br><br> | |||
== 関連コマンドとツール == | |||
* <code>useradd</code> | |||
* <code>usermod</code> | |||
* <code>userdel</code> | |||
*: ユーザアカウントの作成、変更、削除 | |||
* <code>groupadd</code> | |||
* <code>groupmod</code> | |||
* <code>groupdel</code> | |||
*: グループの作成、変更、削除 | |||
* <code>passwd</code> | |||
*: ユーザパスワードの変更 | |||
* <code>chage</code> | |||
*: ユーザパスワードの有効期限設定 | |||
* <code>id</code> | |||
*: ユーザのUID、GID、所属グループの表示 | |||
* <code>groups</code> | |||
*: ユーザの所属グループの表示 | |||
* <code>whoami</code> | |||
*: 現在のユーザ名の表示 | |||
<br><br> | |||
== セキュリティ == | |||
* 最小権限の原則 | |||
*: ユーザには必要最小限の権限のみを付与 | |||
* rootアカウントの使用制限 | |||
*: 日常的なタスクには一般ユーザアカウントを使用 | |||
* 定期的なパスワード変更とパスワードポリシーの実施 | |||
* 未使用アカウントの定期的な監査と削除 | |||
* sudoの適切な設定と使用 | |||
<br><br> | |||
== プログラムでの使用 == | |||
C/C++において、ユーザ情報およびグループ情報にアクセスする主な関数を、以下に示す。<br> | |||
* <code>getpwnam</code>関数 | |||
* <code>getpwuid</code>関数 | |||
*: ユーザ情報の取得 | |||
* <code>getgrnam</code>関数 | |||
* <code>getgrgid</code>関数 | |||
*: グループ情報の取得 | |||
* <code>getpwent</code>関数 | |||
* <code>getgrent</code>関数 | |||
*: 全てのユーザ情報およびグループ情報の順次取得 | |||
<br> | |||
上記の関数を使用する場合は、適切なエラーハンドリングとメモリ管理が重要である。<br> | |||
<br><br> | |||
== Linuxのユーザの取得 == | |||
==== ユーザ名およびホームディレクトリの取得 : Qtライブラリの使用 ==== | |||
以下の例では、Linuxのユーザ名とホームディレクトリを取得している。<br> | |||
<br> | |||
* ユーザ名の取得 | |||
*: 環境変数USERを使用してユーザ名を取得する。 | |||
*: 環境変数USERが空の場合、代替として環境変数USERNAMEを取得する。(一部のシステムでは異なる環境変数を使用する可能性があるため) | |||
* ホームディレクトリの取得 | |||
*: <code>QDir::homePath</code>メソッドを使用して、現在のユーザのホームディレクトリを取得する。 | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
#include <QCoreApplication> | |||
#include <QDir> | |||
#include <QProcessEnvironment> | |||
#include <QDebug> | |||
int main(int argc, char *argv[]) | |||
{ | |||
QCoreApplication a(argc, argv); | |||
// 現在ログインしているユーザ名を取得 | |||
QString userName = qgetenv("USER"); | |||
if (userName.isEmpty()) | |||
userName = qgetenv("USERNAME"); | |||
// 現在ログインしているユーザのホームディレクトリを取得 | |||
QString homeDir = QDir::homePath(); | |||
qDebug() << "Current user name: " << userName; | |||
qDebug() << "Home directory: " << homeDir; | |||
return a.exec(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== ユーザ情報の取得 : libcライブラリの使用 (推奨) ==== | |||
libcライブラリの<code>getpwent</code>関数を使用することにより、システムの標準APIを使用してユーザ情報を取得できる。<br> | |||
これは、/etc/passwdファイルを直接読み込むよりも安全であり、かつ、異なるUNIXシステム間での互換性も高くなる。<br> | |||
<br> | |||
このアプローチは安全で信頼性が高く、システムのセキュリティポリシーに準拠している。<br> | |||
また、/etc/passwdファイルへの直接アクセスを避けることにより、ファイルパーミッションの問題も回避することができる。<br> | |||
<br> | |||
# libcライブラリの<code>getpwent</code>関数、<code>setpwent</code>関数、<code>endpwent</code>関数の標準C関数を使用して、システムのパスワードデータベースにアクセスする。 | |||
# ファイルを直接読み込む代わりにシステムAPIを使用するため、より安全で信頼性が高くなる。 | |||
# 異なるUNIXシステム間での互換性が向上する。 | |||
# 文字エンコーディングの問題を避けるため、<code>QString::fromLocal8Bit</code>メソッドを使用して、システムのローカルエンコーディングから<code>QString</code>クラスに変換している。 | |||
<br> | |||
また、libCryptライブラリをリンクすることにより、一部のシステムで必要となる暗号化関連の関数にアクセスすることができる。<br> | |||
<syntaxhighlight lang="make"> | |||
# Qtプロジェクトファイル (.pro) を使用する場合 | |||
## libCryptライブラリを使用する場合 | |||
## libCryptライブラリを使用しない場合は、以下に示す設定は不要 | |||
# Pkg-configを使用する場合 | |||
CONFIG += link_pkgconfig | |||
PKGCONFIG += libcrypt | |||
# Pkg-configを使用しない場合 | |||
LIBS += -lcrypt | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="cmake"> | |||
# CMakeを使用する場合 (CMakeLists.txtファイル) | |||
## libCryptライブラリを使用する場合 | |||
## libCryptライブラリを使用しない場合は、以下に示す設定は不要 | |||
find_package(PkgConfig REQUIRED) | |||
pkg_check_modules(LIBCRYPT REQUIRED libcrypt) | |||
target_link_libraries(${PROJECT_NAME} PRIVATE | |||
# ...略 | |||
${LIBCRYPT_LIBRARIES} | |||
) | |||
target_include_directories(${PROJECT_NAME} PRIVATE | |||
${LIBCRYPT_INCLUDE_DIRS} | |||
) | |||
target_compile_options(${PROJECT_NAME} PRIVATE | |||
${LIBCRYPT_CFLAGS_OTHER} | |||
) | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
#include <QCoreApplication> | |||
#include <pwd.h> | |||
#include <sys/types.h> | |||
#include <QDebug> | |||
strut UserInfo { | |||
QString username; | |||
QString uid; | |||
QString gid; | |||
QString fullName; | |||
QString homeDir; | |||
QString shell; | |||
}; | |||
QList<UserInfo> getUsers() | |||
{ | |||
QList<UserInfo> users; | |||
struct passwd *pw; | |||
// passwdデータベースの先頭に巻き戻す | |||
setpwent(); | |||
while ((pw = getpwent()) != nullptr) { | |||
UserInfo user; | |||
user.username = QString::fromLocal8Bit(pw->pw_name); | |||
user.uid = QString::number(pw->pw_uid); | |||
user.gid = QString::number(pw->pw_gid); | |||
user.fullName = QString::fromLocal8Bit(pw->pw_gecos); | |||
user.homeDir = QString::fromLocal8Bit(pw->pw_dir); | |||
user.shell = QString::fromLocal8Bit(pw->pw_shell); | |||
users.append(user); | |||
} | |||
// passwdデータベースを閉じる | |||
endpwent(); | |||
return users; | |||
} | |||
int main(int argc, char *argv[]) | |||
{ | |||
QCoreApplication a(argc, argv); | |||
QList<UserInfo> users = getUsers(); | |||
for (const auto &user : users) { | |||
qDebug() << "Username: " << user.username; | |||
qDebug() << "UID: " << user.uid; | |||
qDebug() << "GID: " << user.gid; | |||
qDebug() << "Full Name: " << user.fullName; | |||
qDebug() << "Home Directory: " << user.homeDir; | |||
qDebug() << "Shell: " << user.shell; | |||
} | |||
return a.exec(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== ユーザ情報の取得 : /etc/passwdファイルを読み込む (非推奨) ==== | |||
以下の例では、/etc/passwdファイルを読み込み、ユーザ情報を取得している。<br> | |||
<br> | |||
ただし、/etc/passwdファイルの読み込むには、root権限が必要となる。<br> | |||
そのため、セキュリティ上の理由からより安全な方法 (例: <code>getpwent</code>関数の使用) を使用することを推奨する。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
#include <QCoreApplication> | |||
#include <QFile> | |||
#include <QTextStream> | |||
#include <QStringList> | |||
#include <QDebug> | |||
struct UserInfo { | |||
QString username; | |||
QString uid; | |||
QString gid; | |||
QString fullName; | |||
QString homeDir; | |||
QString shell; | |||
}; | |||
QList<UserInfo> getUsers() | |||
{ | |||
QList<UserInfo> users; | |||
QFile file("/etc/passwd"); | |||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | |||
qDebug() << "Failed to open /etc/passwd"; | |||
return users; | |||
} | |||
QTextStream in(&file); | |||
while (!in.atEnd()) { | |||
QString line = in.readLine(); | |||
QStringList fields = line.split(':'); | |||
if (fields.size() >= 7) { | |||
UserInfo user; | |||
user.username = fields[0]; | |||
user.uid = fields[2]; | |||
user.gid = fields[3]; | |||
user.fullName = fields[4]; | |||
user.homeDir = fields[5]; | |||
user.shell = fields[6]; | |||
users.append(user); | |||
} | |||
} | |||
file.close(); | |||
return users; | |||
} | |||
int main(int argc, char *argv[]) | |||
{ | |||
QCoreApplication a(argc, argv); | |||
QList<UserInfo> users = getUsers(); | |||
for (const auto &user : users) { | |||
qDebug() << "Username: " << user.username; | |||
qDebug() << "UID: " << user.uid; | |||
qDebug() << "GID: " << user.gid; | |||
qDebug() << "Full Name: " << user.fullName; | |||
qDebug() << "Home Directory: " << user.homeDir; | |||
qDebug() << "Shell: " << user.shell; | |||
} | |||
return a.exec(); | |||
} | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||
== Linuxのグループの取得 == | == Linuxのグループの取得 == | ||
以下の例では、現在のユーザが所属しているグループ名を取得している。<br> | 以下の例では、現在のユーザが所属しているグループ名を取得している。<br> | ||
<br> | |||
ただし、この例はUNIX系システム (Linux、MacOS) 向けであるため、Windowsの場合は異なるアプローチが必要になる。<br> | |||
また、libcのシステムヘッダファイル (grp.h、pwd.h、unistd.h、sys/types.h) を使用しているため、クロスプラットフォームの互換性はない。<br> | |||
<br> | <br> | ||
このサンプルコードは、以下に示すような手順で動作する。<br> | このサンプルコードは、以下に示すような手順で動作する。<br> | ||
# まず、現在のユーザのUIDを取得する。 | # まず、現在のユーザのUIDを取得する。 | ||
# UIDを使用してユーザ情報を取得する。 | # UIDを使用してユーザ情報を取得する。 | ||
# | # libcライブラリの<code>getgrouplist</code>関数を使用して、ユーザが所属するグループの数とIDを取得する。 | ||
# | # 各グループIDに対して、libcライブラリの<code>getgrgid</code>関数を使用してグループ名を取得する。 | ||
# 取得したグループ名をQStringListクラスに追加する。 | # 取得したグループ名をQStringListクラスに追加する。 | ||
<br> | <br> | ||