diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9743564 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/libuser-0.60.tar.xz diff --git a/.libuser.metadata b/.libuser.metadata new file mode 100644 index 0000000..8f7331a --- /dev/null +++ b/.libuser.metadata @@ -0,0 +1 @@ +8aa1cd4d7d6a0c3a43a59679efe53fb203409033 SOURCES/libuser-0.60.tar.xz diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/libuser-0.60-ja.po b/SOURCES/libuser-0.60-ja.po new file mode 100644 index 0000000..ebd2938 --- /dev/null +++ b/SOURCES/libuser-0.60-ja.po @@ -0,0 +1,1480 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Red Hat, Inc. +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Hajime Taira , 2011-2012 +# Hirofumi Saito , 2004, 2005, 2006 +# hyuugabaru , 2007, 2009 +# Kiyoto Hashida , 2002 +# Kiyoto Hashida , 2009 +# Makoto Mizukami , 2008 +# Miloslav Trmač , 2011 +# Noriko Mizumoto , 2007, 2008, 2009 +# Tomoyuki KATO , 2011-2013 +# 高一人参 @欠陥遺伝子 , 2011 +# Yukihiro Nakai , 2001 +# amoewaki , 2017. #zanata +# ljanda , 2017. #zanata +# amoewaki , 2018. #zanata +msgid "" +msgstr "" +"Project-Id-Version: libuser 0.60\n" +"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/bugzilla/\n" +"POT-Creation-Date: 2018-01-02 13:27+0100\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revision-Date: 2018-01-09 01:19+0000\n" +"Last-Translator: amoewaki \n" +"Language-Team: Japanese (http://www.transifex.com/projects/p/fedora/language/" +"ja/)\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Zanata 4.3.2\n" + +#: apps/apputil.c:197 apps/apputil.c:201 +#, c-format +msgid "Failed to drop privileges.\n" +msgstr "特権の停止に失敗しました。\n" + +#: apps/apputil.c:210 +#, c-format +msgid "Internal error.\n" +msgstr "内部エラーです。\n" + +#: apps/apputil.c:231 +#, c-format +msgid "%s is not authorized to change the finger info of %s\n" +msgstr "%s が %s の finger 情報を変更するのは許可されていません\n" + +#: apps/apputil.c:233 +msgid "Unknown user context" +msgstr "不明なユーザーのコンテキスト" + +#: apps/apputil.c:241 +#, c-format +msgid "Can't set default context for /etc/passwd\n" +msgstr "/etc/passwd 用のデフォルトのコンテキストが設定できません\n" + +#: apps/apputil.c:250 +#, c-format +msgid "Error initializing PAM.\n" +msgstr "PAM の初期化に失敗\n" + +#: apps/apputil.c:260 apps/apputil.c:287 +#, c-format +msgid "Authentication failed for %s.\n" +msgstr "%s の認証に失敗しました。\n" + +#: apps/apputil.c:268 +#, c-format +msgid "Internal PAM error `%s'.\n" +msgstr "内部 PAM エラー `%s'\n" + +#: apps/apputil.c:273 +#, c-format +msgid "Unknown user authenticated.\n" +msgstr "不明なユーザー認証です。\n" + +#: apps/apputil.c:277 +#, c-format +msgid "User mismatch.\n" +msgstr "ユーザーが一致しませんでした。\n" + +#: apps/lchage.c:84 apps/lchfn.c:53 apps/lchsh.c:44 apps/lgroupadd.c:47 +#: apps/lgroupdel.c:42 apps/lgroupmod.c:54 apps/lid.c:115 apps/lnewusers.c:45 +#: apps/lpasswd.c:47 apps/luseradd.c:55 apps/luserdel.c:45 apps/lusermod.c:56 +msgid "prompt for all information" +msgstr "すべての情報について入力確認する" + +#: apps/lchage.c:86 +msgid "list aging parameters for the user" +msgstr "ユーザーのエージングパラメーターを一覧表示する" + +#: apps/lchage.c:88 +msgid "minimum days between password changes" +msgstr "パスワード変更間隔の最小日数" + +#: apps/lchage.c:88 apps/lchage.c:90 apps/lchage.c:93 apps/lchage.c:96 +#: apps/lchage.c:99 apps/lchage.c:102 +msgid "DAYS" +msgstr "日数" + +#: apps/lchage.c:90 +msgid "maximum days between password changes" +msgstr "パスワード変更後の有効日数" + +#: apps/lchage.c:92 +msgid "date of last password change in days since 1/1/70" +msgstr "パスワード変更日 (1970/1/1 からの日数)" + +#: apps/lchage.c:95 +msgid "" +"number of days after password expiration date when account is considered " +"inactive" +msgstr "パスワード失効後、アカウントが無効であるとみなされるまでの日数" + +#: apps/lchage.c:98 +msgid "password expiration date in days since 1/1/70" +msgstr "パスワード失効日 (1970/1/1 からの日数)" + +#: apps/lchage.c:101 +msgid "days before expiration to begin warning user" +msgstr "ユーザーに警告を開始する、パスワード失効までの日数" + +#: apps/lchage.c:114 apps/lid.c:130 apps/lpasswd.c:68 apps/luseradd.c:100 +#: apps/luserdel.c:59 apps/lusermod.c:101 +msgid "[OPTION...] user" +msgstr "[オプション...] ユーザー" + +#: apps/lchage.c:117 apps/lchfn.c:70 apps/lchsh.c:58 apps/lgroupadd.c:65 +#: apps/lgroupdel.c:56 apps/lgroupmod.c:85 apps/lid.c:133 apps/lnewusers.c:66 +#: apps/lpasswd.c:71 apps/luseradd.c:103 apps/luserdel.c:62 apps/lusermod.c:104 +#, c-format +msgid "Error parsing arguments: %s.\n" +msgstr "引数の構文解析に失敗: %s\n" + +#: apps/lchage.c:126 apps/lpasswd.c:85 apps/luseradd.c:118 apps/luserdel.c:70 +#: apps/lusermod.c:115 +#, c-format +msgid "No user name specified.\n" +msgstr "ユーザー名が指定されていません。\n" + +#: apps/lchage.c:138 apps/lchfn.c:103 apps/lchsh.c:91 apps/lgroupadd.c:102 +#: apps/lgroupdel.c:77 apps/lgroupmod.c:119 apps/lid.c:179 apps/lnewusers.c:79 +#: apps/lpasswd.c:97 apps/luseradd.c:143 apps/luserdel.c:81 apps/lusermod.c:157 +#: samples/enum.c:56 samples/testuser.c:71 +#, c-format +msgid "Error initializing %s: %s.\n" +msgstr "%s の初期化に失敗: %s\n" + +#: apps/lchage.c:147 apps/lchfn.c:114 apps/lchsh.c:102 apps/lpasswd.c:148 +#: apps/luserdel.c:89 apps/lusermod.c:171 +#, c-format +msgid "User %s does not exist.\n" +msgstr "ユーザー %s は存在しません。\n" + +#: apps/lchage.c:160 +#, c-format +msgid "Account is locked.\n" +msgstr "アカウントはロックされています。\n" + +#: apps/lchage.c:162 +#, c-format +msgid "Account is not locked.\n" +msgstr "アカウントはロックされていません。\n" + +#: apps/lchage.c:166 +#, c-format +msgid "Minimum: %ld\n" +msgstr "最小: %ld\n" + +#: apps/lchage.c:170 +#, c-format +msgid "Maximum: %ld\n" +msgstr "最大: %ld\n" + +#: apps/lchage.c:172 +#, c-format +msgid "Maximum: None\n" +msgstr "最大値: なし\n" + +#: apps/lchage.c:175 +#, c-format +msgid "Warning: %ld\n" +msgstr "警告: %ld\n" + +#: apps/lchage.c:180 +#, c-format +msgid "Inactive: %ld\n" +msgstr "無効: %ld\n" + +#: apps/lchage.c:182 +#, c-format +msgid "Inactive: Never\n" +msgstr "無効化: なし\n" + +#: apps/lchage.c:186 apps/lchage.c:194 apps/lchage.c:204 +msgid "Must change password on next login" +msgstr "次回ログイン時に必ずパスワードを変更" + +#: apps/lchage.c:188 apps/lchage.c:196 apps/lchage.c:206 apps/lchage.c:215 +msgid "Never" +msgstr "なし" + +#: apps/lchage.c:191 +#, c-format +msgid "Last Change: %s\n" +msgstr "最終更新: %s\n" + +#: apps/lchage.c:201 +#, c-format +msgid "Password Expires: %s\n" +msgstr "パスワード期限切れ: %s\n" + +#: apps/lchage.c:213 +#, c-format +msgid "Password Inactive: %s\n" +msgstr "パスワード無効: %s\n" + +#: apps/lchage.c:219 +#, c-format +msgid "Account Expires: %s\n" +msgstr "アカウント期限切れ: %s\n" + +#: apps/lchage.c:240 +#, c-format +msgid "Failed to modify aging information for %s: %s\n" +msgstr "%s のエージング情報の更新に失敗しました: %s\n" + +#: apps/lchfn.c:67 apps/lchsh.c:55 +msgid "[OPTION...] [user]" +msgstr "[オプション...] [ユーザー]" + +#: apps/lchfn.c:86 apps/lchsh.c:74 apps/lid.c:164 +#, c-format +msgid "No user name specified, no name for uid %d.\n" +msgstr "ユーザー名が未指定で、uid %d の名前がありません。\n" + +#: apps/lchfn.c:96 +#, c-format +msgid "Changing finger information for %s.\n" +msgstr "%s 用の finger 情報を変更しています。\n" + +#: apps/lchfn.c:136 +msgid "Full Name" +msgstr "フルネーム" + +#: apps/lchfn.c:146 +msgid "Surname" +msgstr "姓" + +#: apps/lchfn.c:157 +msgid "Given Name" +msgstr "名" + +#: apps/lchfn.c:167 +msgid "Office" +msgstr "勤務先" + +#: apps/lchfn.c:176 +msgid "Office Phone" +msgstr "勤務先電話番号" + +#: apps/lchfn.c:185 +msgid "Home Phone" +msgstr "自宅電話番号" + +#: apps/lchfn.c:195 +msgid "E-Mail Address" +msgstr "メールアドレス" + +#: apps/lchfn.c:208 +#, c-format +msgid "Finger information not changed: input error.\n" +msgstr "Finger 情報は変更されていません: 入力エラー\n" + +#: apps/lchfn.c:270 +msgid "Finger information changed.\n" +msgstr "Finger 情報が変更されました。\n" + +#: apps/lchfn.c:273 +#, c-format +msgid "Finger information not changed: %s.\n" +msgstr "Finger 情報は変更されていません: %s\n" + +#: apps/lchsh.c:84 +#, c-format +msgid "Changing shell for %s.\n" +msgstr "%s 用にシェルを変更中\n" + +#: apps/lchsh.c:114 +msgid "New Shell" +msgstr "新規のシェル" + +#: apps/lchsh.c:121 apps/lchsh.c:136 +#, c-format +msgid "Shell not changed: %s\n" +msgstr "シェル変更不可能: %s\n" + +#: apps/lchsh.c:133 +msgid "Shell changed.\n" +msgstr "シェル変更済み\n" + +#: apps/lgroupadd.c:49 +msgid "gid for new group" +msgstr "新しいグループの GID" + +#: apps/lgroupadd.c:49 apps/lgroupmod.c:56 apps/lpasswd.c:56 apps/lpasswd.c:59 +#: apps/luseradd.c:67 apps/lusermod.c:66 apps/lusermod.c:68 +msgid "NUM" +msgstr "番号" + +#: apps/lgroupadd.c:51 +msgid "create a system group" +msgstr "システムグループを作成します" + +#: apps/lgroupadd.c:62 apps/lgroupdel.c:53 apps/lgroupmod.c:82 +msgid "[OPTION...] group" +msgstr "[オプション...] グループ" + +#: apps/lgroupadd.c:74 apps/lgroupdel.c:65 apps/lgroupmod.c:93 +#, c-format +msgid "No group name specified.\n" +msgstr "グループ名は指定されていません。\n" + +#: apps/lgroupadd.c:87 apps/lgroupmod.c:105 apps/lnewusers.c:172 +#: apps/luseradd.c:164 apps/lusermod.c:127 +#, c-format +msgid "Invalid group ID %s\n" +msgstr "無効なグループ ID: %s\n" + +#: apps/lgroupadd.c:119 +#, c-format +msgid "Group creation failed: %s\n" +msgstr "グループの作成に失敗しました: %s\n" + +#: apps/lgroupdel.c:85 apps/lgroupmod.c:132 apps/lpasswd.c:153 +#, c-format +msgid "Group %s does not exist.\n" +msgstr "グループ %s は存在しません。\n" + +#: apps/lgroupdel.c:91 +#, c-format +msgid "Group %s could not be deleted: %s\n" +msgstr "グループ %s は削除できませんでした: %s\n" + +#: apps/lgroupmod.c:56 +msgid "set GID for group" +msgstr "グループの GID を設定します" + +#: apps/lgroupmod.c:58 +msgid "change group to have given name" +msgstr "グループを、指定された名前に変更する" + +#: apps/lgroupmod.c:58 +msgid "NAME" +msgstr "名前" + +#: apps/lgroupmod.c:60 apps/luseradd.c:75 +msgid "plaintext password for use with group" +msgstr "グループに用いる平文パスワード" + +#: apps/lgroupmod.c:60 apps/lgroupmod.c:62 apps/lgroupmod.c:64 +#: apps/lgroupmod.c:66 apps/lgroupmod.c:68 apps/lgroupmod.c:70 +#: apps/lpasswd.c:51 apps/lpasswd.c:53 apps/luseradd.c:59 apps/luseradd.c:61 +#: apps/luseradd.c:63 apps/luseradd.c:65 apps/luseradd.c:69 apps/luseradd.c:75 +#: apps/luseradd.c:77 apps/luseradd.c:79 apps/luseradd.c:81 apps/luseradd.c:83 +#: apps/luseradd.c:85 apps/luseradd.c:87 apps/luseradd.c:89 apps/lusermod.c:58 +#: apps/lusermod.c:60 apps/lusermod.c:64 apps/lusermod.c:70 apps/lusermod.c:72 +#: apps/lusermod.c:74 apps/lusermod.c:80 apps/lusermod.c:82 apps/lusermod.c:84 +#: apps/lusermod.c:86 apps/lusermod.c:88 apps/lusermod.c:90 +msgid "STRING" +msgstr "文字列" + +#: apps/lgroupmod.c:62 apps/luseradd.c:77 +msgid "pre-hashed password for use with group" +msgstr "グループに用いるハッシュ化パスワード" + +#: apps/lgroupmod.c:64 +msgid "list of administrators to add" +msgstr "追加する管理者の一覧" + +#: apps/lgroupmod.c:66 +msgid "list of administrators to remove" +msgstr "削除する管理者の一覧" + +#: apps/lgroupmod.c:68 +msgid "list of group members to add" +msgstr "追加するグループメンバーの一覧" + +#: apps/lgroupmod.c:70 +msgid "list of group members to remove" +msgstr "削除するグループメンバーの一覧" + +#: apps/lgroupmod.c:71 +msgid "lock group" +msgstr "グループをロックします" + +#: apps/lgroupmod.c:72 +msgid "unlock group" +msgstr "グループのロックを解除します" + +#: apps/lgroupmod.c:125 apps/lusermod.c:164 +#, c-format +msgid "Both -L and -U specified.\n" +msgstr "-L と -U の両方のオプションが指定されています。\n" + +#: apps/lgroupmod.c:139 apps/lgroupmod.c:148 +#, c-format +msgid "Failed to set password for group %s: %s\n" +msgstr "グループ %s のパスワード設定に失敗しました: %s\n" + +#: apps/lgroupmod.c:157 +#, c-format +msgid "Group %s could not be locked: %s\n" +msgstr "グループ %s はロックされませんでした: %s\n" + +#: apps/lgroupmod.c:166 +#, c-format +msgid "Group %s could not be unlocked: %s\n" +msgstr "グループ %s はロック解除できませんでした: %s\n" + +#: apps/lgroupmod.c:242 apps/lgroupmod.c:257 +#, c-format +msgid "Group %s could not be modified: %s\n" +msgstr "グループ %s は修正できませんでした: %s\n" + +#: apps/lid.c:42 apps/lid.c:74 apps/lid.c:188 +#, c-format +msgid "Error looking up %s: %s\n" +msgstr "%s の検索に失敗: %s\n" + +#: apps/lid.c:117 +msgid "" +"list members of a named group instead of the group memberships for the named " +"user" +msgstr "指定された名前のユーザーがメンバーであるグループの代わりに、指定された名前のグループのメンバーを一覧表示します" + +#: apps/lid.c:120 +msgid "only list membership information by name, and not UID/GID" +msgstr "UID/GID ではなく、名前でのみメンバー情報を一覧表示する" + +#: apps/lid.c:146 +#, c-format +msgid "No group name specified, using %s.\n" +msgstr "グループ名は未指定です。%s を使用中\n" + +#: apps/lid.c:150 +#, c-format +msgid "No group name specified, no name for gid %d.\n" +msgstr "グループ名は未指定です。gid %d の名前は未設定\n" + +#: apps/lid.c:160 +#, c-format +msgid "No user name specified, using %s.\n" +msgstr "ユーザー名が未指定です。%s を使用中\n" + +#: apps/lid.c:192 +#, c-format +msgid "%s does not exist\n" +msgstr "%s は存在しません。\n" + +#: apps/lnewusers.c:47 +msgid "file with user information records" +msgstr "ユーザー情報レコードを持つファイル" + +#: apps/lnewusers.c:47 +msgid "PATH" +msgstr "パス" + +#: apps/lnewusers.c:49 +msgid "don't create home directories" +msgstr "ホームディレクトリーを作成しない" + +#: apps/lnewusers.c:51 +msgid "don't create mail spools" +msgstr "メールスプールを作成しない" + +#: apps/lnewusers.c:63 +msgid "[OPTION...]" +msgstr "[オプション...]" + +#: apps/lnewusers.c:88 +#, c-format +msgid "Error opening `%s': %s.\n" +msgstr "%s の読み込みエラー: %s\n" + +#: apps/lnewusers.c:118 +#, c-format +msgid "Error creating account for `%s': line improperly formatted.\n" +msgstr "`%s' 用のアカウント作成に失敗: 不正な書式が含まれています。\n" + +#: apps/lnewusers.c:129 apps/luseradd.c:128 apps/lusermod.c:142 +#, c-format +msgid "Invalid user ID %s\n" +msgstr "無効なユーザー ID %s\n" + +#: apps/lnewusers.c:136 +msgid "Refusing to create account with UID 0.\n" +msgstr "UID:0 でのアカウント作成を拒否中です。\n" + +#: apps/lnewusers.c:206 +#, c-format +msgid "Error creating group for `%s' with GID %jd: %s\n" +msgstr "%s 用に、GID %jd でグループの作成中にエラーが発生しました: %s\n" + +#: apps/lnewusers.c:246 +#, c-format +msgid "Refusing to use dangerous home directory `%s' for %s by default\n" +msgstr "デフォルトで、%s 用の危険なホームディレクトリー %s の使用を拒否中です\n" + +#: apps/lnewusers.c:257 +#, c-format +msgid "Error creating home directory for %s: %s\n" +msgstr "%s 用の新規ホームディレクトリー作成に失敗しました: %s\n" + +#: apps/lnewusers.c:270 +#, c-format +msgid "Error creating mail spool for %s: %s\n" +msgstr "%s のメールスプールの作成中にエラーが発生しました: %s\n" + +#: apps/lnewusers.c:285 +#, c-format +msgid "Error setting initial password for %s: %s\n" +msgstr "%s 用の初期パスワード設定中にエラーが発生しました: %s\n" + +#: apps/lnewusers.c:295 +#, c-format +msgid "Error creating user account for %s: %s\n" +msgstr "%s 用のユーザーアカウント作成に失敗しました: %s。\n" + +#: apps/lpasswd.c:49 +msgid "set group password instead of user password" +msgstr "ユーザーのパスワードの代わりにグループのパスワードを設定します" + +#: apps/lpasswd.c:51 +msgid "new plain password" +msgstr "新しい平文パスワード" + +#: apps/lpasswd.c:53 +msgid "new crypted password" +msgstr "新しい暗号文パスワード" + +#: apps/lpasswd.c:55 +msgid "read new plain password from given descriptor" +msgstr "指定された記述子から新しい平文パスワードを読み込みます" + +#: apps/lpasswd.c:58 +msgid "read new crypted password from given descriptor" +msgstr "指定された記述子から新しい暗号パスワードを読み込みます" + +#: apps/lpasswd.c:83 +#, c-format +msgid "Changing password for %s.\n" +msgstr "%s のパスワード変更中にエラー。\n" + +#: apps/lpasswd.c:111 +msgid "New password" +msgstr "新規パスワード" + +#: apps/lpasswd.c:114 +msgid "New password (confirm)" +msgstr "新規パスワード (確認)" + +#: apps/lpasswd.c:128 +#, c-format +msgid "Passwords do not match, try again.\n" +msgstr "パスワードが一致しません。もう一度やり直してください。\n" + +#: apps/lpasswd.c:133 +#, c-format +msgid "Password change canceled.\n" +msgstr "パスワード変更は取り消されました。\n" + +#: apps/lpasswd.c:165 apps/lpasswd.c:182 +#, c-format +msgid "Error reading from file descriptor %d.\n" +msgstr "エラー: ファイルディスクリプター %d から読み込めません。\n" + +#: apps/lpasswd.c:203 apps/luseradd.c:302 apps/luseradd.c:311 +#, c-format +msgid "Error setting password for user %s: %s.\n" +msgstr "ユーザー %s のパスワード設定に失敗: %s。\n" + +#: apps/lpasswd.c:212 +#, c-format +msgid "Error setting password for group %s: %s.\n" +msgstr "グループ %s のパスワード設定中にエラーが発生しました: %s 。\n" + +#: apps/lpasswd.c:224 +#, c-format +msgid "Password changed.\n" +msgstr "パスワード変更済み。\n" + +#: apps/luseradd.c:57 +msgid "create a system user" +msgstr "システムユーザーを作成する" + +#: apps/luseradd.c:59 +msgid "GECOS information for new user" +msgstr "新しいユーザーの GECOS 情報" + +#: apps/luseradd.c:61 +msgid "home directory for new user" +msgstr "新しいユーザーのホームディレクトリー" + +#: apps/luseradd.c:63 +msgid "directory with files for the new user" +msgstr "新しいユーザー向けファイルを持つディレクトリー" + +#: apps/luseradd.c:65 +msgid "shell for new user" +msgstr "新しいユーザーのシェル" + +#: apps/luseradd.c:67 +msgid "uid for new user" +msgstr "新しいユーザーの UID" + +#: apps/luseradd.c:69 +msgid "group for new user" +msgstr "新しいユーザーのグループ" + +#: apps/luseradd.c:71 +msgid "don't create home directory for user" +msgstr "ユーザーのホームディレクトリーを作成しない" + +#: apps/luseradd.c:73 +msgid "don't create group with same name as user" +msgstr "ユーザーと同じ名前のグループを作成しない" + +#: apps/luseradd.c:79 +msgid "common name for new user" +msgstr "新しいユーザーの一般名" + +#: apps/luseradd.c:81 +msgid "given name for new user" +msgstr "新しいユーザーの名" + +#: apps/luseradd.c:83 +msgid "surname for new user" +msgstr "新しいユーザーの姓" + +#: apps/luseradd.c:85 +msgid "room number for new user" +msgstr "新しいユーザーの部屋番号" + +#: apps/luseradd.c:87 +msgid "telephone number for new user" +msgstr "新しいユーザーの電話番号" + +#: apps/luseradd.c:89 +msgid "home telephone number for new user" +msgstr "新しいユーザーの自宅電話番号" + +#: apps/luseradd.c:189 +#, c-format +msgid "Group %jd does not exist\n" +msgstr "グループ %jd は存在しません\n" + +#: apps/luseradd.c:207 apps/luseradd.c:220 +#, c-format +msgid "Error creating group `%s': %s\n" +msgstr "グループ `%s' の作成に失敗: %s\n" + +#: apps/luseradd.c:260 +#, c-format +msgid "Account creation failed: %s.\n" +msgstr "アカウントの作成に失敗しました: %s。\n" + +#: apps/luseradd.c:283 +#, c-format +msgid "Error creating %s: %s.\n" +msgstr "%s の作成に失敗: %s。\n" + +#: apps/luseradd.c:290 +#, c-format +msgid "Error creating mail spool: %s\n" +msgstr "メールスプールの作成中にエラーが発生しました: %s\n" + +#: apps/luserdel.c:47 +msgid "don't remove the user's private group, if the user has one" +msgstr "ユーザーがプライベートグループを持っていても、それを削除しません。" + +#: apps/luserdel.c:50 +msgid "remove the user's home directory" +msgstr "ユーザーのホームディレクトリーを削除する" + +#: apps/luserdel.c:94 +#, c-format +msgid "User %s could not be deleted: %s.\n" +msgstr "ユーザー %s は削除できませんでした: %s。\n" + +#: apps/luserdel.c:108 +#, c-format +msgid "%s did not have a gid number.\n" +msgstr "%s には GID 番号がありません。\n" + +#: apps/luserdel.c:114 +#, c-format +msgid "No group with GID %jd exists, not removing.\n" +msgstr "GID %jd のグループが存在しないため、削除しません。\n" + +#: apps/luserdel.c:120 +#, c-format +msgid "Group with GID %jd did not have a group name.\n" +msgstr "GID %jd のグループにはグループ名がありません。\n" + +#: apps/luserdel.c:126 +#, c-format +msgid "Group %s could not be deleted: %s.\n" +msgstr "グループ %s は削除できませんでした: %s。\n" + +#: apps/luserdel.c:139 +#, c-format +msgid "Error removing home directory: %s.\n" +msgstr "ホームディレクトリーの削除中にエラーが発生しました: %s\n" + +#: apps/luserdel.c:145 +#, c-format +msgid "Error removing mail spool: %s" +msgstr "メールスプールの削除中にエラーが発生しました: %s" + +#: apps/lusermod.c:58 +msgid "GECOS information" +msgstr "GECOS の情報" + +#: apps/lusermod.c:60 +msgid "home directory" +msgstr "ホームディレクトリー" + +#: apps/lusermod.c:62 +msgid "move home directory contents" +msgstr "ホームディレクトリーの内容を移動する" + +#: apps/lusermod.c:64 +msgid "set shell for user" +msgstr "ユーザーのシェルを設定する" + +#: apps/lusermod.c:66 +msgid "set UID for user" +msgstr "ユーザーの UID を設定する" + +#: apps/lusermod.c:68 +msgid "set primary GID for user" +msgstr "ユーザーのプライマリー GID を設定する" + +#: apps/lusermod.c:70 +msgid "change login name for user" +msgstr "ユーザーのログイン名を変更する" + +#: apps/lusermod.c:72 +msgid "plaintext password for the user" +msgstr "ユーザーの平文パスワード" + +#: apps/lusermod.c:74 +msgid "pre-hashed password for the user" +msgstr "ユーザーのハッシュ済みパスワード" + +#: apps/lusermod.c:75 +msgid "lock account" +msgstr "アカウントをロックする" + +#: apps/lusermod.c:78 +msgid "unlock account" +msgstr "アカウントのロックを解除する" + +#: apps/lusermod.c:80 +msgid "set common name for user" +msgstr "ユーザーの一般名を設定する" + +#: apps/lusermod.c:82 +msgid "set given name for user" +msgstr "ユーザーの名を設定する" + +#: apps/lusermod.c:84 +msgid "set surname for user" +msgstr "ユーザーの姓を設定する" + +#: apps/lusermod.c:86 +msgid "set room number for user" +msgstr "ユーザーの部屋番号を設定する" + +#: apps/lusermod.c:88 +msgid "set telephone number for user" +msgstr "ユーザーの電話番号を設定する" + +#: apps/lusermod.c:90 +msgid "set home telephone number for user" +msgstr "ユーザーの自宅電話番号を設定する" + +#: apps/lusermod.c:180 apps/lusermod.c:193 +#, c-format +msgid "Failed to set password for user %s: %s.\n" +msgstr "ユーザーのパスワード設定に失敗 %s: %s。\n" + +#: apps/lusermod.c:203 +#, c-format +msgid "User %s could not be locked: %s.\n" +msgstr "ユーザー %s はロックできませんでした: %s。\n" + +#: apps/lusermod.c:211 +#, c-format +msgid "User %s could not be unlocked: %s.\n" +msgstr "ユーザー %s のロックを解除できませんでした: %s。\n" + +#: apps/lusermod.c:232 +#, c-format +msgid "Warning: Group with ID %jd does not exist.\n" +msgstr "警告: グループ ID %jd は存在しません。\n" + +#: apps/lusermod.c:275 +#, c-format +msgid "User %s could not be modified: %s.\n" +msgstr "ユーザー %s は編集できませんでした: %s\n" + +#: apps/lusermod.c:326 +#, c-format +msgid "Group %s could not be modified: %s.\n" +msgstr "グループ %s は修正できませんでした:%s\n" + +#: apps/lusermod.c:342 +#, c-format +msgid "No old home directory for %s.\n" +msgstr "%s には、古いホームディレクトリーがありません。\n" + +#: apps/lusermod.c:347 +#, c-format +msgid "No new home directory for %s.\n" +msgstr "%s には、新しいホームディレクトリーがありません。\n" + +#: apps/lusermod.c:353 +#, c-format +msgid "Error moving %s to %s: %s.\n" +msgstr "%s を %s に移動できませんでした: %s\n" +"\n" + +#: lib/config.c:128 +#, c-format +msgid "could not open configuration file `%s': %s" +msgstr "設定ファイル `%s' を開けませんでした: %s" + +#: lib/config.c:134 +#, c-format +msgid "could not stat configuration file `%s': %s" +msgstr "設定ファイル `%s' を stat できませんでした: %s" + +#: lib/config.c:143 +#, c-format +msgid "configuration file `%s' is too large" +msgstr "設定ファイル `%s' が大きすぎます" + +#: lib/config.c:159 +#, c-format +msgid "could not read configuration file `%s': %s" +msgstr "設定ファイル `%s' を開けませんでした: %s" + +#: lib/error.c:62 +msgid "success" +msgstr "成功" + +#: lib/error.c:64 +msgid "module disabled by configuration" +msgstr "モジュールが設定で無効になっています。" + +#: lib/error.c:66 +msgid "generic error" +msgstr "一般エラー" + +#: lib/error.c:68 +msgid "not enough privileges" +msgstr "権限がありません" + +#: lib/error.c:70 +msgid "access denied" +msgstr "アクセスが拒否されました" + +#: lib/error.c:72 +msgid "bad user/group name" +msgstr "正しくないユーザー名/グループ名" + +#: lib/error.c:74 +msgid "bad user/group id" +msgstr "正しくないユーザー ID/グループ ID" + +#: lib/error.c:76 +msgid "user/group name in use" +msgstr "ユーザー名/グループ名は使われています" + +#: lib/error.c:78 +msgid "user/group id in use" +msgstr "ユーザー ID/グループ ID は使われています" + +#: lib/error.c:80 +msgid "error manipulating terminal attributes" +msgstr "端末属性の取得にエラーが発生しました" + +#: lib/error.c:82 +msgid "error opening file" +msgstr "ファイルの読み込みに失敗" + +#: lib/error.c:84 +msgid "error locking file" +msgstr "ファイルのロックに失敗" + +#: lib/error.c:86 +msgid "error statting file" +msgstr "ファイルの stat 情報取得に失敗" + +#: lib/error.c:88 +msgid "error reading file" +msgstr "ファイルの読み込み中にエラーが発生しました" + +#: lib/error.c:90 +msgid "error writing to file" +msgstr "ファイルへの書き込み中にエラーが発生しました" + +#: lib/error.c:92 +msgid "data not found in file" +msgstr "ファイルでデータが見つかりませんでした" + +#: lib/error.c:94 +msgid "internal initialization error" +msgstr "内部の初期化に失敗" + +#: lib/error.c:96 +msgid "error loading module" +msgstr "モジュールのロードに失敗" + +#: lib/error.c:98 +msgid "error resolving symbol in module" +msgstr "モジュールのシンボル解決に失敗しました。" + +#: lib/error.c:100 +msgid "library/module version mismatch" +msgstr "ライブラリー/モジュールのバージョン不一致" + +#: lib/error.c:102 +msgid "unlocking would make the password field empty" +msgstr "ロックを解除するとパスワード領域は空になります" + +#: lib/error.c:105 +msgid "invalid attribute value" +msgstr "無効な属性の値です" + +#: lib/error.c:107 +msgid "invalid module combination" +msgstr "無効なモジュールの組み合わせです" + +#: lib/error.c:109 +msgid "user's home directory not owned by them" +msgstr "所有されていないユーザーのホームディレクトリー" + +#: lib/error.c:115 +msgid "unknown error" +msgstr "不明なエラーが発生しました" + +#: lib/misc.c:240 +msgid "invalid number" +msgstr "無効な番号" + +#: lib/misc.c:254 +msgid "invalid ID" +msgstr "無効な ID" + +#: lib/modules.c:61 +#, c-format +msgid "no initialization function %s in `%s'" +msgstr "`%s' の関数 %s で初期化できません" + +#: lib/modules.c:79 +#, c-format +msgid "module version mismatch in `%s'" +msgstr "`%s' のモジュールバージョンの不一致" + +#: lib/modules.c:92 +#, c-format +msgid "module `%s' does not define `%s'" +msgstr "モジュール `%s' が `%s' を定義していません" + +#: lib/prompt.c:88 +msgid "error reading terminal attributes" +msgstr "端末属性の読み込み中にエラーが発生しました" + +#: lib/prompt.c:95 lib/prompt.c:107 +msgid "error setting terminal attributes" +msgstr "端末属性の設定中にエラーが発生しました" + +#: lib/prompt.c:101 +msgid "error reading from terminal" +msgstr "端末から読み込み中にエラーが発生しました" + +#: lib/user.c:218 +msgid "name is not set" +msgstr "名前が設定されていません" + +#: lib/user.c:223 +msgid "name is too short" +msgstr "名前が短すぎます" + +#: lib/user.c:228 +#, c-format +msgid "name is too long (%zu > %d)" +msgstr "名前が長すぎます (%zu > %d)" + +#: lib/user.c:235 +msgid "name contains non-ASCII characters" +msgstr "名前に ASCII 以外の文字があります" + +#: lib/user.c:242 +msgid "name contains control characters" +msgstr "名前が制御文字を含んでいます" + +#: lib/user.c:249 +msgid "name contains whitespace" +msgstr "名前に空白があります" + +#: lib/user.c:261 +msgid "name starts with a hyphen" +msgstr "名前がハイフンから始まっています" + +#: lib/user.c:272 +#, c-format +msgid "name contains invalid char `%c'" +msgstr "名前に無効な文字 `%c' があります" + +#: lib/user.c:308 lib/user.c:360 +#, c-format +msgid "user %s has no UID" +msgstr "ユーザー %s には UID がありません。" + +#: lib/user.c:310 +#, c-format +msgid "user %s not found" +msgstr "ユーザー %s が見つかりませんでした" + +#: lib/user.c:333 lib/user.c:361 +#, c-format +msgid "group %s has no GID" +msgstr "グループ %s には GID がありません。" + +#: lib/user.c:335 +#, c-format +msgid "group %s not found" +msgstr "グループ %s が見つかりませんでした" + +#: lib/user.c:355 +#, c-format +msgid "user %jd has no name" +msgstr "ユーザー %jd には名前がありません。" + +#: lib/user.c:356 +#, c-format +msgid "group %jd has no name" +msgstr "グループ %jd には名前がありません。" + +#: lib/user.c:364 +msgid "user has neither a name nor an UID" +msgstr "ユーザーには、名前もしくは UID がありません。" + +#: lib/user.c:365 +msgid "group has neither a name nor a GID" +msgstr "グループには、名前もしくは GID がありません。" + +#: lib/user.c:1311 +#, c-format +msgid "Refusing to use dangerous home directory `%s' by default" +msgstr "デフォルトで危険なホームディレクトリ `%s' の使用を拒否中です" + +#: lib/user.c:2310 +#, c-format +msgid "Invalid default value of field %s: %s" +msgstr "領域 %s の値は無効なデフォルト値です: %s" + +#: lib/util.c:300 modules/files.c:374 +#, c-format +msgid "error locking file: %s" +msgstr "ファイルのロック中にエラーが発生しました: %s" + +#: lib/util.c:706 +#, c-format +msgid "couldn't get default security context: %s" +msgstr "デフォルトのセキュリティーコンテキストを取得できません: %s" + +#: lib/util.c:733 lib/util.c:759 lib/util.c:785 +#, c-format +msgid "couldn't get security context of `%s': %s" +msgstr "`%s' のセキュリティーコンテキストを取得できません: %s" + +#: lib/util.c:739 lib/util.c:765 lib/util.c:791 lib/util.c:823 +#, c-format +msgid "couldn't set default security context to `%s': %s" +msgstr "`%s' にデフォルトのセキュリティーコンテキストを設定できません: %s" + +#: lib/util.c:815 +#, c-format +msgid "couldn't determine security context for `%s': %s" +msgstr "`%s' のセキュリティーコンテキストを決定できません: %s" + +#: modules/files.c:129 modules/files.c:692 modules/files.c:1585 +#: modules/files.c:1920 modules/files.c:1930 modules/files.c:2012 +#: modules/files.c:2023 modules/files.c:2089 modules/files.c:2101 +#: modules/files.c:2191 modules/files.c:2200 modules/files.c:2255 +#: modules/files.c:2264 modules/files.c:2359 modules/files.c:2368 +#, c-format +msgid "couldn't open `%s': %s" +msgstr "`%s' を開けません: %s" + +#: modules/files.c:137 modules/files.c:994 modules/files.c:1187 +#: modules/files.c:1329 +#, c-format +msgid "couldn't stat `%s': %s" +msgstr "`%s' の stat 情報を取得できません: %s" + +#: modules/files.c:161 +#, c-format +msgid "error creating `%s': %s" +msgstr "`%s' の作成中にエラーが発生しました: %s" + +#: modules/files.c:169 +#, c-format +msgid "Error changing owner of `%s': %s" +msgstr "`%s' の所有者変更に失敗: %s" + +#: modules/files.c:175 +#, c-format +msgid "Error changing mode of `%s': %s" +msgstr "エラー: `%s' のモードを変更できません: %s " + +#: modules/files.c:191 +#, c-format +msgid "Error reading `%s': %s" +msgstr "`%s'の読み込みに失敗: %s" + +#: modules/files.c:206 modules/files.c:217 modules/files.c:305 +#: modules/files.c:467 +#, c-format +msgid "Error writing `%s': %s" +msgstr "`%s'の書き込みに失敗: %s" + +#: modules/files.c:247 modules/files.c:1005 modules/files.c:1195 +#: modules/files.c:1338 +#, c-format +msgid "couldn't read from `%s': %s" +msgstr "`%s' から読み込めません: %s" + +#: modules/files.c:256 +#, c-format +msgid "Invalid contents of lock `%s'" +msgstr "ロック `%s' の内容が無効です。" + +#: modules/files.c:261 +#, c-format +msgid "The lock %s is held by process %ju" +msgstr "ロック %s は、プロセス %ju に保持されています。" + +#: modules/files.c:269 +#, c-format +msgid "Error removing stale lock `%s': %s" +msgstr "古いロック `%s' を削除する際にエラーが発生しました: %s" + +#: modules/files.c:297 +#, c-format +msgid "error opening temporary file for `%s': %s" +msgstr "`%s' の一時ファイルを開く際にエラーが発生しました: %s" + +#: modules/files.c:321 +#, c-format +msgid "Cannot obtain lock `%s': %s" +msgstr "ロック `%s' を取得できません: %s" + +#: modules/files.c:434 +#, c-format +msgid "Error resolving `%s': %s" +msgstr "`%s' を解決する際にエラーが発生しました: %s" + +#: modules/files.c:442 +#, c-format +msgid "Error replacing `%s': %s" +msgstr "`%s' を置き換える際にエラーが発生しました: %s" + +#: modules/files.c:903 +#, c-format +msgid "%s value `%s': `\\n' not allowed" +msgstr "%s 値 `%s': `\\n' は許可されていません" + +#: modules/files.c:910 +#, c-format +msgid "%s value `%s': `:' not allowed" +msgstr "%s 値 `%s': `:' は許可されていません" + +#: modules/files.c:1014 +msgid "entry already present in file" +msgstr "エントリーは、ファイルに存在します" + +#: modules/files.c:1021 modules/files.c:1031 modules/files.c:1041 +#: modules/files.c:1393 modules/files.c:1401 modules/files.c:1409 +#, c-format +msgid "couldn't write to `%s': %s" +msgstr "`%s' に書き込めません: %s" + +#: modules/files.c:1173 +#, c-format +msgid "entity object has no %s attribute" +msgstr "エンティティーオブジェクトに %s 属性がありません" + +#: modules/files.c:1215 +msgid "entry with conflicting name already present in file" +msgstr "競合する名前のエントリーは、ファイルに存在します" + +#: modules/files.c:1803 +msgid "`:' and `\\n' not allowed in encrypted password" +msgstr "`:' および `\\n' は、暗号化パスワードでは許可されていません" + +#: modules/files.c:1815 modules/ldap.c:1543 modules/ldap.c:1812 +msgid "error encrypting password" +msgstr "パスワードの暗号化中にエラーが発生しました" + +#: modules/files.c:2517 modules/ldap.c:2410 +#, c-format +msgid "the `%s' and `%s' modules can not be combined" +msgstr "`%s' と `%s' のモジュールは、組み合わせることができません。" + +#: modules/files.c:2601 modules/files.c:2679 +msgid "not executing with superuser privileges" +msgstr "スーパーユーザー特権で実行できません" + +#: modules/files.c:2692 +msgid "no shadow file present -- disabling" +msgstr "shadow ファイルはありません。無効になっています" + +#: modules/krb5.c:100 +#, c-format +msgid "" +"error connecting to the kadm5 server for service `%s' in realm `%s': %s" +msgstr "レルム `%s' のサービス `%s' で、kadm5 サーバーに接続できません: %s" + +#: modules/krb5.c:132 modules/krb5.c:198 modules/krb5.c:297 modules/krb5.c:385 +#: modules/krb5.c:437 modules/krb5.c:525 modules/krb5.c:591 +msgid "error initializing kerberos library" +msgstr "kerberos ライブラリーの初期化でエラーが発生しました" + +#: modules/krb5.c:139 modules/krb5.c:219 modules/krb5.c:329 modules/krb5.c:337 +#: modules/krb5.c:405 modules/krb5.c:458 modules/krb5.c:546 modules/krb5.c:608 +#, c-format +msgid "error parsing user name `%s' for kerberos" +msgstr "kerberos のユーザー名 `%s' で、構文解析エラーが発生しました" + +#: modules/krb5.c:209 modules/krb5.c:396 modules/krb5.c:448 modules/krb5.c:536 +#, c-format +msgid "entity structure has no %s or %s attributes" +msgstr "エンティティー構造体には、%s 属性および %s 属性がありません。" + +#: modules/krb5.c:307 +#, c-format +msgid "entity has no %s or %s attributes" +msgstr "エンティティーには、%s 属性および %s 属性がありません。" + +#: modules/krb5.c:320 +#, c-format +msgid "entity was created with no %s or %s attributes" +msgstr "エンティティーは、%s 属性や %s 属性を含まずに作成されました" + +#: modules/krb5.c:471 modules/krb5.c:559 +#, c-format +msgid "error reading information for `%s' from kerberos" +msgstr "kerberos から `%s' の情報を読み込んでいる時に、エラーが発生しました" + +#: modules/krb5.c:600 +#, c-format +msgid "entity has no %s attribute" +msgstr "エンティティーには、 %s 属性がありません" + +#: modules/krb5.c:638 +#, c-format +msgid "error setting password for `%s'" +msgstr "`%s' のパスワード設定中にエラーが発生しました" + +#: modules/krb5.c:764 +msgid "Kerberos Realm" +msgstr "kerberos レルム" + +#: modules/krb5.c:771 +msgid "Kerberos Admin Principal" +msgstr "kerberos 管理プリンシパル" + +#: modules/krb5.c:793 +msgid "Kerberos Password for Admin Principal" +msgstr "管理プリンシパルの kerberos パスワード" + +#: modules/ldap.c:199 +msgid "error initializing ldap library" +msgstr "LDAP ライブラリーの初期化時にエラー" + +#: modules/ldap.c:210 +#, c-format +msgid "could not set LDAP protocol to version %d" +msgstr "LDAP プロトコルをバージョン %d に設定できませんでした" + +#: modules/ldap.c:229 +msgid "could not negotiate TLS with LDAP server" +msgstr "LDAP サーバーと TLS ネゴシエートできませんでした" + +#: modules/ldap.c:424 +msgid "could not bind to LDAP server" +msgstr "LDAP サーバーとバインドできませんでした" + +#: modules/ldap.c:427 +#, c-format +msgid "could not bind to LDAP server, first attempt as `%s': %s" +msgstr "LDAP サーバーとバインドできませんでした。最初に `%s' として試みます: %s" + +#: modules/ldap.c:1315 +#, c-format +msgid "user object had no %s attribute" +msgstr "ユーザーオブジェクトには、%s 属性がありません" + +#: modules/ldap.c:1324 +#, c-format +msgid "user object was created with no `%s'" +msgstr "ユーザーオブジェクトは、`%s' を含まずに生成されました" + +#: modules/ldap.c:1344 +#, c-format +msgid "error creating a LDAP directory entry: %s" +msgstr "LDAP ディレクトリーエントリーの作成時にエラーが発生しました: %s" + +#: modules/ldap.c:1370 modules/ldap.c:1604 +#, c-format +msgid "error modifying LDAP directory entry: %s" +msgstr "LDAP ディレクトリーエントリーの変更時にエラーが発生しました: %s" + +#: modules/ldap.c:1395 +#, c-format +msgid "error renaming LDAP directory entry: %s" +msgstr "LDAP ディレクトリーエントリーの名前変更でエラー: %s" + +#: modules/ldap.c:1440 +#, c-format +msgid "object had no %s attribute" +msgstr "オブジェクトには、%s 属性がありません" + +#: modules/ldap.c:1456 +#, c-format +msgid "error removing LDAP directory entry: %s" +msgstr "LDAP ディレクトリーエントリーの削除時にエラー: %s" + +#: modules/ldap.c:1506 modules/ldap.c:1521 modules/ldap.c:1635 +#: modules/ldap.c:1730 +#, c-format +msgid "object has no %s attribute" +msgstr "オブジェクトには、%s 属性がありません" + +#: modules/ldap.c:1533 +msgid "unsupported password encryption scheme" +msgstr "サポートされていないパスワード暗号化スキームです" + +#: modules/ldap.c:1658 +msgid "no such object in LDAP directory" +msgstr "LDAP ディレクトリーには、そのようなオブジェクトがありません" + +#: modules/ldap.c:1670 +#, c-format +msgid "no `%s' attribute found" +msgstr "`%s' 属性は見つかりませんでした" + +#: modules/ldap.c:1843 +#, c-format +msgid "error setting password in LDAP directory for %s: %s" +msgstr "%s の LDAP ディレクトリーのパスワード設定でエラー: %s" + +#: modules/ldap.c:2446 +msgid "LDAP Server Name" +msgstr "LDAP サーバー名" + +#: modules/ldap.c:2452 +msgid "LDAP Search Base DN" +msgstr "LDAP 検索ベース DN" + +#: modules/ldap.c:2458 +msgid "LDAP Bind DN" +msgstr "LDAP バインド DN" + +#: modules/ldap.c:2465 +msgid "LDAP Bind Password" +msgstr "LDAP バインドパスワード" + +#: modules/ldap.c:2471 +msgid "LDAP SASL User" +msgstr "LDAP SASL ユーザー" + +#: modules/ldap.c:2478 +msgid "LDAP SASL Authorization User" +msgstr "LDAP SASL 認証ユーザー" + +#: modules/sasldb.c:132 +#, c-format +msgid "Cyrus SASL error creating user: %s" +msgstr "ユーザーの作成時に Cyrus SASL エラー: %s" + +#: modules/sasldb.c:136 +#, c-format +msgid "Cyrus SASL error removing user: %s" +msgstr "ユーザーの削除時に Cyrus SASL エラー: %s" + +#: modules/sasldb.c:503 modules/sasldb.c:511 +#, c-format +msgid "error initializing Cyrus SASL: %s" +msgstr "Cyrus SASL の初期化に失敗: %s" + +#: python/admin.c:518 +msgid "error creating home directory for user" +msgstr "ユーザー用のホームディレクトリー作成に失敗しました" + +#: python/admin.c:557 python/admin.c:596 +msgid "error removing home directory for user" +msgstr "ユーザーのホームディレクトリー削除に失敗しました" + +#: python/admin.c:667 +msgid "error moving home directory for user" +msgstr "ユーザーのホームディレクトリー移動に失敗しました" + +#: samples/lookup.c:63 +#, c-format +msgid "Error initializing %s: %s\n" +msgstr "%s の初期化に失敗: %s\n" + +#: samples/lookup.c:76 +#, c-format +msgid "Invalid ID %s\n" +msgstr "無効な ID %s\n" + +#: samples/lookup.c:88 +#, c-format +msgid "Searching for group with ID %jd.\n" +msgstr "ID %jd のグループを検索中。\n" + +#: samples/lookup.c:92 +#, c-format +msgid "Searching for group named %s.\n" +msgstr "名前が %s のグループを検索中。\n" + +#: samples/lookup.c:99 +#, c-format +msgid "Searching for user with ID %jd.\n" +msgstr "ID %jd のユーザーを検索中。\n" + +#: samples/lookup.c:103 +#, c-format +msgid "Searching for user named %s.\n" +msgstr "名前が %s のユーザーを検索中。\n" + +#: samples/lookup.c:117 +msgid "Entry not found.\n" +msgstr "エントリーは見つかりませんでした。\n" + +#: samples/prompt.c:48 +msgid "Prompts succeeded.\n" +msgstr "指示成功。\n" + +#: samples/prompt.c:58 +msgid "Prompts failed.\n" +msgstr "指示失敗。\n" + +#: samples/testuser.c:76 +msgid "Default user object classes:\n" +msgstr "デフォルトユーザーオブジェクトクラス:\n" + +#: samples/testuser.c:82 +msgid "Default user attribute names:\n" +msgstr "デフォルトユーザー属性名:\n" + +#: samples/testuser.c:88 +msgid "Getting default user attributes:\n" +msgstr "デフォルトユーザー属性を取得中:\n" + +#: samples/testuser.c:95 +msgid "Copying user structure:\n" +msgstr "ユーザー構造体をコピー中:\n" + diff --git a/SOURCES/libuser-CVE-2015-3246.patch b/SOURCES/libuser-CVE-2015-3246.patch new file mode 100644 index 0000000..ca58b47 --- /dev/null +++ b/SOURCES/libuser-CVE-2015-3246.patch @@ -0,0 +1,1530 @@ +2015-06-26 Miloslav Trmač + + * modules/files.c (open_and_copy_file): Replace and heavily modify ... + (lu_files_create_backup): ... this. + (lock_file_handle_existing, lock_file_create, lock_file_remove) + (struct editing, editing_open, replace_file_or_symlink) + (editing_close): New functions. + (generic_lookup, generic_is_locked, lu_files_enumerate) + (lu_files_users_enumerate_by_group, lu_files_groups_enumerate_by_user) + (lu_files_enumerate_full): Remove locking on read-only operations. + (generic_add, generic_mod, generic_del, generic_lock) + (generic_setpass): Use struct editing instead of dealing with locking, + backups, SELinux individually. + + * lib/user_private.h (lu_util_lock_obtain, lu_util_lock_free): Mark + as deprecated. + + * lib/util.c (lu_util_field_write): Fail on an incomplete write(). + +2015-06-25 Miloslav Trmač + + * modules/files.c (format_generic, generic_setpass): Refuse to write + field values which contain \n. + * tests/files_test.py (Tests.testUserAdd9, Tests.testUserMod8) + (tests.testUserSetpass5, tests.testGroupAdd6, tests.testGroupMod7) + (tests.testGroupSetpass4): New tests. + +diff -up libuser-0.60/lib/user_private.h.CVE-2015-3246 libuser-0.60/lib/user_private.h +--- libuser-0.60/lib/user_private.h.CVE-2015-3246 2013-10-12 23:56:07.000000000 +0200 ++++ libuser-0.60/lib/user_private.h 2015-07-08 15:15:14.060544103 +0200 +@@ -330,9 +330,11 @@ typedef char lu_security_context_t; /* " + ((void)(PATH), (void)(MODE), (void)(ERROR), TRUE) + #endif + +-/* Lock a file. */ ++#ifndef LU_DISABLE_DEPRECATED ++/* Lock a file. Deprecated. */ + gpointer lu_util_lock_obtain(int fd, struct lu_error **error); + void lu_util_lock_free(gpointer lock); ++#endif + + /* Manipulate a colon-delimited flat text file. */ + char *lu_util_line_get_matching1(int fd, const char *firstpart, +diff -up libuser-0.60/lib/util.c.CVE-2015-3246 libuser-0.60/lib/util.c +--- libuser-0.60/lib/util.c.CVE-2015-3246 2013-10-12 23:56:07.000000000 +0200 ++++ libuser-0.60/lib/util.c 2015-07-08 15:15:14.060544103 +0200 +@@ -632,7 +632,7 @@ lu_util_field_write(int fd, const char * + goto err; + } + len = strlen(buf); +- if (write(fd, buf, len) == -1) { ++ if (write(fd, buf, len) != len) { + lu_error_new(error, lu_error_write, NULL); + ret = FALSE; + goto err; +diff -up libuser-0.60/modules/files.c.CVE-2015-3246 libuser-0.60/modules/files.c +--- libuser-0.60/modules/files.c.CVE-2015-3246 2013-10-12 23:56:07.000000000 +0200 ++++ libuser-0.60/modules/files.c 2015-07-08 15:16:41.014981429 +0200 +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -101,82 +102,79 @@ module_filename(struct lu_module *module + return g_strconcat(dir, file_suffix, NULL); + } + +-/* Create a backup copy of "filename" named "filename-". */ +-static gboolean +-lu_files_create_backup(const char *filename, +- struct lu_error **error) ++/* Copy contents of INPUT_FILENAME to OUTPUT_FILENAME, exclusively creating it ++ * if EXCLUSIVE. ++ * Return the file descriptor for OUTPUT_FILENAME, open for reading and writing, ++ * or -1 on error. ++ * Note that this does no locking and assumes the directories hosting the files ++ * are not being manipulated by an attacker. */ ++static int ++open_and_copy_file(const char *input_filename, const char *output_filename, ++ gboolean exclusive, struct lu_error **error) + { + int ifd, ofd; +- gpointer ilock, olock; +- char *backupname; +- struct stat ist, ost; +- off_t offset; +- gboolean res = FALSE; ++ struct stat st; ++ int res = -1; ++ int flags; + +- g_assert(filename != NULL); +- g_assert(strlen(filename) > 0); ++ g_assert(input_filename != NULL); ++ g_assert(strlen(input_filename) > 0); ++ g_assert(output_filename != NULL); ++ g_assert(strlen(output_filename) > 0); + +- /* Open the original file. */ +- ifd = open(filename, O_RDONLY); ++ /* Open the input file. */ ++ ifd = open(input_filename, O_RDONLY); + if (ifd == -1) { + lu_error_new(error, lu_error_open, +- _("couldn't open `%s': %s"), filename, ++ _("couldn't open `%s': %s"), input_filename, + strerror(errno)); + goto err; + } + +- /* Lock the input file. */ +- if ((ilock = lu_util_lock_obtain(ifd, error)) == NULL) +- goto err_ifd; +- + /* Read the input file's size. */ +- if (fstat(ifd, &ist) == -1) { ++ if (fstat(ifd, &st) == -1) { + lu_error_new(error, lu_error_stat, +- _("couldn't stat `%s': %s"), filename, ++ _("couldn't stat `%s': %s"), input_filename, + strerror(errno)); +- goto err_ilock; ++ goto err_ifd; + } + +- /* Generate the backup file's name and open it, creating it if it +- * doesn't already exist. */ +- backupname = g_strconcat(filename, "-", NULL); +- ofd = open(backupname, O_WRONLY | O_CREAT, ist.st_mode); ++ /* We only need O_WRONLY, but the caller needs RDWR if ofd will be ++ * used as e->new_fd. */ ++ flags = O_RDWR | O_CREAT; ++ if (exclusive) { ++ /* This ensures that if there is a concurrent writer which is ++ * not doing locking for some reason, we will not truncate their ++ * temporary file. Still, the other writer may truncate our ++ * file, and ultimately the rename() committing the changes will ++ * lose one or the other set of changes. */ ++ (void)unlink(output_filename); ++ flags |= O_EXCL; ++ } else ++ flags |= O_TRUNC; ++ /* Start with absolutely restrictive permissions to make sure nobody ++ * can get a file descriptor for this file until we are done resetting ++ * ownership. */ ++ ofd = open(output_filename, flags, 0); + if (ofd == -1) { + lu_error_new(error, lu_error_open, +- _("error creating `%s': %s"), backupname, ++ _("error creating `%s': %s"), output_filename, + strerror(errno)); +- goto err_backupname; +- } +- +- /* If we can't read its type, or it's not a normal file, bail. */ +- if (fstat(ofd, &ost) == -1) { +- lu_error_new(error, lu_error_stat, _("couldn't stat `%s': %s"), +- backupname, strerror(errno)); +- goto err_ofd; +- } +- if (!S_ISREG(ost.st_mode)) { +- lu_error_new(error, lu_error_open, +- _("backup file `%s' exists and is not a regular file"), +- backupname); +- goto err_ofd; ++ goto err_ifd; + } + +- /* Now lock the output file. */ +- if ((olock = lu_util_lock_obtain(ofd, error)) == NULL) +- goto err_ofd; +- + /* Set the permissions on the new file to match the old one. */ +- if (fchown(ofd, ist.st_uid, ist.st_gid) == -1 && errno != EPERM) { ++ if (fchown(ofd, st.st_uid, st.st_gid) == -1 && errno != EPERM) { + lu_error_new(error, lu_error_generic, +- _("Error changing owner of `%s': %s"), backupname, +- strerror(errno)); +- goto err_olock; ++ _("Error changing owner of `%s': %s"), ++ output_filename, strerror(errno)); ++ goto err_ofd; + } +- if (fchmod(ofd, ist.st_mode) == -1) { ++ if (fchmod(ofd, st.st_mode) == -1) { + lu_error_new(error, lu_error_generic, +- _("Error changing mode of `%s': %s"), backupname, +- strerror(errno)); +- goto err_olock; ++ _("Error changing mode of `%s': %s"), ++ output_filename, strerror(errno)); ++ goto err_ofd; + } + + /* Copy the data, block by block. */ +@@ -190,9 +188,9 @@ lu_files_create_backup(const char *filen + if (errno == EINTR) + continue; + lu_error_new(error, lu_error_read, +- _("Error reading `%s': %s"), filename, +- strerror(errno)); +- goto err_olock; ++ _("Error reading `%s': %s"), ++ input_filename, strerror(errno)); ++ goto err_ofd; + } + if (left == 0) + break; +@@ -206,55 +204,297 @@ lu_files_create_backup(const char *filen + continue; + lu_error_new(error, lu_error_write, + _("Error writing `%s': %s"), +- backupname, strerror(errno)); +- goto err_olock; ++ output_filename, strerror(errno)); ++ goto err_ofd; + } + p += out; + left -= out; + } + } + +- /* Flush data to disk, and truncate at the current offset. This is +- * necessary if the file existed before we opened it. */ +- fsync(ofd); +- offset = lseek(ofd, 0, SEEK_CUR); +- if (offset == -1 || ftruncate(ofd, offset) == -1) { +- lu_error_new(error, lu_error_generic, +- _("Error writing `%s': %s"), backupname, +- strerror(errno)); +- goto err_olock; +- } +- +- /* Re-read data about the output file. */ +- if (fstat(ofd, &ost) == -1) { +- lu_error_new(error, lu_error_stat, +- _("couldn't stat `%s': %s"), backupname, +- strerror(errno)); +- goto err_olock; +- } +- +- /* Complain if the files are somehow not the same. */ +- if (ist.st_size != ost.st_size) { +- lu_error_new(error, lu_error_generic, +- _("backup file size mismatch")); +- goto err_olock; ++ /* Flush data to disk. */ ++ if (fsync(ofd) != 0 || lseek(ofd, 0, SEEK_SET) == -1) { ++ lu_error_new(error, lu_error_write, _("Error writing `%s': %s"), ++ output_filename, strerror(errno)); ++ goto err_ofd; + } +- res = TRUE; ++ res = ofd; ++ goto err_ifd; /* Do not close ofd */ + +- err_olock: +- lu_util_lock_free(olock); + err_ofd: + close(ofd); +- err_backupname: +- g_free(backupname); +- err_ilock: +- lu_util_lock_free(ilock); + err_ifd: + close(ifd); + err: + return res; + } + ++/* Deal with an existing LOCK_FILENAME. ++ * Return TRUE if the caller should try again. */ ++static gboolean ++lock_file_handle_existing(const char *lock_filename, struct lu_error **error) ++{ ++ gchar *lock_contents; ++ GError *gerror; ++ gboolean ret = FALSE; ++ uintmax_t pid; ++ char *p; ++ ++ gerror = NULL; ++ if (g_file_get_contents(lock_filename, &lock_contents, NULL, &gerror) ++ == FALSE) { ++ lu_error_new(error, lu_error_read, ++ _("couldn't read from `%s': %s"), lock_filename, ++ gerror->message); ++ g_error_free(gerror); ++ goto err; ++ } ++ errno = 0; ++ pid = strtoumax(lock_contents, &p, 10); ++ if (errno != 0 || *p != 0 || p == lock_contents || (pid_t)pid != pid) { ++ lu_error_new(error, lu_error_lock, ++ _("Invalid contents of lock `%s'"), lock_filename); ++ goto err_lock_contents; ++ } ++ if (kill(pid, 0) == 0 || errno != ESRCH) { ++ lu_error_new(error, lu_error_lock, ++ _("The lock %s is held by process %ju"), ++ lock_filename, pid); ++ goto err_lock_contents; ++ } ++ /* This is unfixably racy, but that should matter only if a genuine ++ * lock owner crashes. */ ++ if (unlink(lock_filename) != 0) { ++ lu_error_new(error, lu_error_lock, ++ _("Error removing stale lock `%s': %s"), lock_filename, ++ strerror(errno)); ++ goto err_lock_contents; ++ } ++ ret = TRUE; ++ /* Fall through */ ++ ++err_lock_contents: ++ g_free(lock_contents); ++err: ++ return ret; ++} ++ ++/* Create a lock file for FILENAME. */ ++static gboolean ++lock_file_create(const char *filename, struct lu_error **error) ++{ ++ char *lock_filename, *tmp_filename; ++ char pid_string[sizeof (pid_t) * CHAR_BIT + 1]; ++ int fd; ++ gboolean ret = FALSE; ++ ++ lock_filename = g_strconcat(filename, ".lock", NULL); ++ tmp_filename = g_strdup_printf("%s.lock.XXXXXX", filename); ++ ++ fd = mkstemp(tmp_filename); ++ if (fd == -1) { ++ lu_error_new(error, lu_error_open, ++ _("error opening temporary file for `%s': %s"), ++ lock_filename, strerror(errno)); ++ goto err_tmp_filename; ++ } ++ if (snprintf(pid_string, sizeof(pid_string), "%ju", (uintmax_t)getpid()) ++ >= sizeof(pid_string)) ++ g_assert_not_reached(); ++ if (write(fd, pid_string, strlen(pid_string)) != strlen(pid_string)) { ++ lu_error_new(error, lu_error_write, _("Error writing `%s': %s"), ++ tmp_filename, strerror(errno)); ++ close(fd); ++ goto err_tmp_file; ++ } ++ close(fd); ++ ++ if (link(tmp_filename, lock_filename) != 0) { ++ if (errno == EEXIST) { ++ if (lock_file_handle_existing(lock_filename, error) ++ == FALSE) ++ goto err_tmp_file; ++ if (link(tmp_filename, lock_filename) == 0) ++ goto got_link; ++ } ++ lu_error_new(error, lu_error_lock, ++ _("Cannot obtain lock `%s': %s"), lock_filename, ++ strerror(errno)); ++ goto err_tmp_file; ++ } ++got_link: ++ ret = TRUE; ++ /* Fall through */ ++ ++err_tmp_file: ++ (void)unlink(tmp_filename); ++err_tmp_filename: ++ g_free(tmp_filename); ++ g_free(lock_filename); ++ return ret; ++} ++ ++/* Remove the lock file for FILENAME. */ ++static void ++lock_file_remove(const char *filename) ++{ ++ char *lock_file; ++ ++ lock_file = g_strconcat(filename, ".lock", NULL); ++ (void)unlink(lock_file); ++ g_free(lock_file); ++} ++ ++/* State related to a file currently open for editing. */ ++struct editing { ++ char *filename; ++ lu_security_context_t fscreate; ++ char *new_filename; ++ int new_fd; ++}; ++ ++/* Open and lock FILE_SUFFIX in MODULE for editing. ++ * Return editing state, or NULL on error. */ ++static struct editing * ++editing_open(struct lu_module *module, const char *file_suffix, ++ struct lu_error **error) ++{ ++ struct editing *e; ++ char *backup_name; ++ int fd; ++ ++ e = g_malloc0(sizeof (*e)); ++ e->filename = module_filename(module, file_suffix); ++ /* Make sure this all works if e->filename is a symbolic link, at least ++ * as long as it points to the same file system. */ ++ ++ if (geteuid() == 0) { ++ if (lckpwdf() != 0) { ++ lu_error_new(error, lu_error_lock, ++ _("error locking file: %s"), ++ strerror(errno)); ++ goto err_filename; ++ } ++ } ++ if (lock_file_create(e->filename, error) == FALSE) ++ goto err_lckpwdf; ++ ++ if (!lu_util_fscreate_save(&e->fscreate, error)) ++ goto err_locked; ++ if (!lu_util_fscreate_from_file(e->filename, error)) ++ goto err_fscreate; ++ ++ backup_name = g_strconcat(e->filename, "-", NULL); ++ fd = open_and_copy_file(e->filename, backup_name, FALSE, error); ++ g_free (backup_name); ++ close(fd); ++ if (fd == -1) ++ goto err_fscreate; ++ ++ e->new_filename = g_strconcat(e->filename, "+", NULL); ++ e->new_fd = open_and_copy_file(e->filename, e->new_filename, TRUE, ++ error); ++ if (e->new_fd == -1) ++ goto err_new_filename; ++ ++ return e; ++ ++err_new_filename: ++ g_free(e->new_filename); ++err_fscreate: ++ lu_util_fscreate_restore(e->fscreate); ++ ++err_locked: ++ (void)lock_file_remove(e->filename); ++err_lckpwdf: ++ if (geteuid() == 0) ++ (void)ulckpwdf(); ++ ++err_filename: ++ g_free(e->filename); ++ g_free(e); ++ return NULL; ++} ++ ++ ++/* Replace DESTINATION with SOURCE, even if DESTINATION is a symbolic link. */ ++static gboolean ++replace_file_or_symlink(const char *source, const char *destination, ++ struct lu_error **error) ++{ ++ struct stat st; ++ char *tmp; ++ gboolean ret = FALSE; ++ ++ tmp = NULL; ++ if (lstat(destination, &st) == 0 && S_ISLNK(st.st_mode)) { ++ tmp = realpath(destination, NULL); ++ if (tmp == NULL) { ++ lu_error_new(error, lu_error_generic, ++ _("Error resolving `%s': %s"), destination, ++ strerror(errno)); ++ goto err; ++ } ++ destination = tmp; ++ } ++ if (rename(source, destination) != 0) { ++ lu_error_new(error, lu_error_write, ++ _("Error replacing `%s': %s"), destination, ++ strerror(errno)); ++ goto err; ++ } ++ ret = TRUE; ++ /* Fall through */ ++ ++err: ++ free(tmp); ++ return ret; ++} ++ ++/* Finish editing E, commit edits if COMMIT. ++ * Return true only if RET_INPUT and everything went OK; suggested usage is ++ * ret = editing_close(e, commit, ret, error); */ ++static gboolean ++editing_close(struct editing *e, gboolean commit, gboolean ret_input, ++ struct lu_error **error) ++{ ++ gboolean ret = FALSE; ++ gboolean unlink_new_filename = TRUE; ++ ++ g_assert(e != NULL); ++ ++ if (commit && fsync(e->new_fd) != 0) { ++ lu_error_new(error, lu_error_write, _("Error writing `%s': %s"), ++ e->new_filename, strerror(errno)); ++ close(e->new_fd); ++ goto err; ++ } ++ close(e->new_fd); ++ ++ if (commit) { ++ if (replace_file_or_symlink(e->new_filename, e->filename, ++ error) == FALSE) ++ goto err; ++ unlink_new_filename = FALSE; ++ } ++ ret = ret_input; ++ ++err: ++ if (unlink_new_filename) ++ (void)unlink(e->new_filename); ++ g_free(e->new_filename); ++ lu_util_fscreate_restore(e->fscreate); ++ ++ (void)lock_file_remove(e->filename); ++ if (geteuid() == 0) ++ (void)ulckpwdf(); ++ ++ g_free(e->filename); ++ g_free(e); ++ return ret; ++} ++ ++ + /* Read a line from the file, no matter how long it is, and return it as a + * newly-allocated string, with the terminator intact. */ + static char * +@@ -435,7 +675,6 @@ generic_lookup(struct lu_module *module, + { + gboolean ret; + int fd = -1; +- gpointer lock; + char *line, *filename; + + g_assert(module != NULL); +@@ -446,7 +685,7 @@ generic_lookup(struct lu_module *module, + + filename = module_filename(module, file_suffix); + +- /* Open the file and lock it. */ ++ /* Open the file. */ + fd = open(filename, O_RDONLY); + if (fd == -1) { + lu_error_new(error, lu_error_open, +@@ -457,15 +696,9 @@ generic_lookup(struct lu_module *module, + } + g_free(filename); + +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) { +- close(fd); +- return FALSE; +- } +- + /* Search for the entry in this file. */ + line = lu_util_line_get_matchingx(fd, name, field, error); + if (line == NULL) { +- lu_util_lock_free(lock); + close(fd); + return FALSE; + } +@@ -473,7 +706,6 @@ generic_lookup(struct lu_module *module, + /* If we found data, parse it and then free the data. */ + ret = parser(line, ent); + g_free(line); +- lu_util_lock_free(lock); + close(fd); + + return ret; +@@ -666,6 +898,13 @@ format_generic(struct lu_ent *ent, const + char *field; + + field = format_field(ent, formats + i); ++ if (strchr(field, '\n') != NULL) { ++ lu_error_new(error, lu_error_invalid_attribute_value, ++ _("%s value `%s': `\\n' not allowed"), ++ formats[i].attribute, field); ++ g_free(field); ++ goto err; ++ } + if (i != format_count - 1 && strchr(field, ':') != NULL) { + lu_error_new(error, lu_error_invalid_attribute_value, + _("%s value `%s': `:' not allowed"), +@@ -729,11 +968,9 @@ generic_add(struct lu_module *module, co + const struct format_specifier *formats, size_t format_count, + struct lu_ent *ent, struct lu_error **error) + { +- lu_security_context_t fscreate; +- char *line, *filename, *contents; +- int fd; ++ struct editing *e; ++ char *line, *contents; + ssize_t r; +- gpointer lock; + struct stat st; + off_t offset; + gboolean ret = FALSE; +@@ -743,50 +980,30 @@ generic_add(struct lu_module *module, co + g_assert(format_count > 0); + g_assert(ent != NULL); + +- filename = module_filename(module, file_suffix); +- + line = format_generic(ent, formats, format_count, error); + if (line == NULL) +- goto err_filename; ++ goto err; + +- if (!lu_util_fscreate_save(&fscreate, error)) ++ e = editing_open(module, file_suffix, error); ++ if (e == NULL) + goto err_line; +- if (!lu_util_fscreate_from_file(filename, error)) +- goto err_fscreate; +- +- /* Create a backup copy of the file we're about to modify. */ +- if (lu_files_create_backup(filename, error) == FALSE) +- goto err_fscreate; +- +- /* Open the file. */ +- fd = open(filename, O_RDWR); +- if (fd == -1) { +- lu_error_new(error, lu_error_open, +- _("couldn't open `%s': %s"), filename, +- strerror(errno)); +- goto err_fscreate; +- } +- +- /* Lock the file. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) +- goto err_fd; + + /* Read the file's size. */ +- if (fstat(fd, &st) == -1) { ++ if (fstat(e->new_fd, &st) == -1) { + lu_error_new(error, lu_error_stat, +- _("couldn't stat `%s': %s"), filename, ++ _("couldn't stat `%s': %s"), e->new_filename, + strerror(errno)); +- goto err_lock; ++ goto err_editing; + } + + /* Read the entire file in. There's some room for improvement here, + * but at least we still have the lock, so it's not going to get + * funky on us. */ + contents = g_malloc0(st.st_size + 1); +- if (read(fd, contents, st.st_size) != st.st_size) { ++ if (read(e->new_fd, contents, st.st_size) != st.st_size) { + lu_error_new(error, lu_error_read, + _("couldn't read from `%s': %s"), +- filename, strerror(errno)); ++ e->new_filename, strerror(errno)); + goto err_contents; + } + +@@ -798,54 +1015,43 @@ generic_add(struct lu_module *module, co + goto err_contents; + } + /* Hooray, we can add this entry at the end of the file. */ +- offset = lseek(fd, 0, SEEK_END); ++ offset = lseek(e->new_fd, 0, SEEK_END); + if (offset == -1) { + lu_error_new(error, lu_error_write, + _("couldn't write to `%s': %s"), +- filename, strerror(errno)); ++ e->new_filename, strerror(errno)); + goto err_contents; + } + /* If the last byte in the file isn't a newline, add one, and silently + * curse people who use text editors (which shall remain unnamed) which + * allow saving of the file without a final line terminator. */ + if ((st.st_size > 0) && (contents[st.st_size - 1] != '\n')) { +- if (write(fd, "\n", 1) != 1) { ++ if (write(e->new_fd, "\n", 1) != 1) { + lu_error_new(error, lu_error_write, + _("couldn't write to `%s': %s"), +- filename, +- strerror(errno)); ++ e->new_filename, strerror(errno)); + goto err_contents; + } + } + /* Attempt to write the entire line to the end. */ +- r = write(fd, line, strlen(line)); ++ r = write(e->new_fd, line, strlen(line)); + if ((size_t)r != strlen(line)) { + /* Oh, come on! */ + lu_error_new(error, lu_error_write, +- _("couldn't write to `%s': %s"), +- filename, ++ _("couldn't write to `%s': %s"), e->new_filename, + strerror(errno)); +- /* Truncate off whatever we actually managed to write and +- * give up. */ +- (void)ftruncate(fd, offset); + goto err_contents; + } +- /* Hey, it succeeded. */ + ret = TRUE; + /* Fall through */ + + err_contents: + g_free(contents); +-err_lock: +- lu_util_lock_free(lock); +-err_fd: +- close(fd); +-err_fscreate: +- lu_util_fscreate_restore(fscreate); ++err_editing: ++ ret = editing_close(e, ret, ret, error); /* Commit/rollback happens here. */ + err_line: + g_free(line); +-err_filename: +- g_free(filename); ++err: + return ret; + } + +@@ -938,11 +1144,9 @@ generic_mod(struct lu_module *module, co + const struct format_specifier *formats, size_t format_count, + struct lu_ent *ent, struct lu_error **error) + { +- lu_security_context_t fscreate; +- char *filename, *new_line, *contents, *line, *rest; ++ struct editing *e; ++ char *new_line, *contents, *line, *rest; + char *current_name, *fragment; +- int fd; +- gpointer lock; + const char *name_attribute; + gboolean ret = FALSE; + struct stat st; +@@ -971,43 +1175,24 @@ generic_mod(struct lu_module *module, co + return FALSE; + } + +- filename = module_filename(module, file_suffix); +- + new_line = format_generic(ent, formats, format_count, error); + if (new_line == NULL) +- goto err_filename; ++ goto err_current_name; + +- if (!lu_util_fscreate_save(&fscreate, error)) ++ e = editing_open(module, file_suffix, error); ++ if (e == NULL) + goto err_new_line; +- if (!lu_util_fscreate_from_file(filename, error)) +- goto err_fscreate; +- /* Create a backup file. */ +- if (lu_files_create_backup(filename, error) == FALSE) +- goto err_fscreate; + +- /* Open the file to be modified. */ +- fd = open(filename, O_RDWR); +- if (fd == -1) { +- lu_error_new(error, lu_error_open, +- _("couldn't open `%s': %s"), filename, +- strerror(errno)); +- goto err_fscreate; +- } +- +- /* Lock the file. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) +- goto err_fd; +- +- if (fstat(fd, &st) == -1) { ++ if (fstat(e->new_fd, &st) == -1) { + lu_error_new(error, lu_error_stat, _("couldn't stat `%s': %s"), +- filename, strerror(errno)); +- goto err_lock; ++ e->new_filename, strerror(errno)); ++ goto err_editing; + } + + contents = g_malloc(st.st_size + 1 + strlen(new_line)); +- if (read(fd, contents, st.st_size) != st.st_size) { ++ if (read(e->new_fd, contents, st.st_size) != st.st_size) { + lu_error_new(error, lu_error_read, +- _("couldn't read from `%s': %s"), filename, ++ _("couldn't read from `%s': %s"), e->new_filename, + strerror(errno)); + goto err_contents; + } +@@ -1045,16 +1230,16 @@ generic_mod(struct lu_module *module, co + memmove(line + strlen(new_line), rest, + contents + st.st_size + 1 - rest); + memcpy(line, new_line, strlen(new_line)); +- if (lseek(fd, line - contents, SEEK_SET) == -1) { ++ if (lseek(e->new_fd, line - contents, SEEK_SET) == -1) { + lu_error_new(error, lu_error_write, NULL); + goto err_contents; + } + len = strlen(line); +- if ((size_t)write(fd, line, len) != len) { ++ if ((size_t)write(e->new_fd, line, len) != len) { + lu_error_new(error, lu_error_write, NULL); + goto err_contents; + } +- if (ftruncate(fd, (line - contents) + len) != 0) { ++ if (ftruncate(e->new_fd, (line - contents) + len) != 0) { + lu_error_new(error, lu_error_write, NULL); + goto err_contents; + } +@@ -1063,16 +1248,11 @@ generic_mod(struct lu_module *module, co + + err_contents: + g_free(contents); +-err_lock: +- lu_util_lock_free(lock); +-err_fd: +- close(fd); +-err_fscreate: +- lu_util_fscreate_restore(fscreate); ++err_editing: ++ ret = editing_close(e, ret, ret, error); /* Commit/rollback happens here. */ + err_new_line: + g_free(new_line); +-err_filename: +- g_free(filename); ++err_current_name: + g_free(current_name); + return ret; + } +@@ -1118,16 +1298,14 @@ static gboolean + generic_del(struct lu_module *module, const char *file_suffix, + struct lu_ent *ent, struct lu_error **error) + { +- lu_security_context_t fscreate; ++ struct editing *e; + char *name; +- char *contents, *filename; ++ char *contents; + char *fragment2; + struct stat st; + size_t len; +- int fd; +- gboolean ret = FALSE; ++ gboolean commit = FALSE, ret = FALSE; + gboolean found; +- gpointer lock; + + /* Get the entity's current name. */ + if (ent->type == lu_user) +@@ -1141,42 +1319,23 @@ generic_del(struct lu_module *module, co + g_assert(module != NULL); + g_assert(ent != NULL); + +- filename = module_filename(module, file_suffix); +- +- if (!lu_util_fscreate_save(&fscreate, error)) +- goto err_filename; +- if (!lu_util_fscreate_from_file(filename, error)) +- goto err_fscreate; +- /* Create a backup of that file. */ +- if (lu_files_create_backup(filename, error) == FALSE) +- goto err_fscreate; +- +- /* Open the file to be modified. */ +- fd = open(filename, O_RDWR); +- if (fd == -1) { +- lu_error_new(error, lu_error_open, +- _("couldn't open `%s': %s"), filename, +- strerror(errno)); +- goto err_fscreate; +- } +- +- /* Lock the file. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) +- goto err_fd; ++ e = editing_open(module, file_suffix, error); ++ if (e == NULL) ++ goto err_name; + + /* Determine the file's size. */ +- if (fstat(fd, &st) == -1) { ++ if (fstat(e->new_fd, &st) == -1) { + lu_error_new(error, lu_error_stat, +- _("couldn't stat `%s': %s"), filename, ++ _("couldn't stat `%s': %s"), e->new_filename, + strerror(errno)); +- goto err_lock; ++ goto err_editing; + } + + /* Allocate space to hold the file and read it all in. */ + contents = g_malloc(st.st_size + 1); +- if (read(fd, contents, st.st_size) != st.st_size) { ++ if (read(e->new_fd, contents, st.st_size) != st.st_size) { + lu_error_new(error, lu_error_read, +- _("couldn't read from `%s': %s"), filename, ++ _("couldn't read from `%s': %s"), e->new_filename, + strerror(errno)); + goto err_contents; + } +@@ -1229,41 +1388,38 @@ generic_del(struct lu_module *module, co + + /* Otherwise we need to write the new data to the file. Jump back to + * the beginning of the file. */ +- if (lseek(fd, 0, SEEK_SET) == -1) { ++ if (lseek(e->new_fd, 0, SEEK_SET) == -1) { + lu_error_new(error, lu_error_write, +- _("couldn't write to `%s': %s"), filename, ++ _("couldn't write to `%s': %s"), e->new_filename, + strerror(errno)); + goto err_contents; + } + + /* Write the new contents out. */ +- if ((size_t)write(fd, contents, len) != len) { ++ if ((size_t)write(e->new_fd, contents, len) != len) { + lu_error_new(error, lu_error_write, +- _("couldn't write to `%s': %s"), filename, ++ _("couldn't write to `%s': %s"), e->new_filename, + strerror(errno)); + goto err_contents; + } + + /* Truncate the file to the new (certainly shorter) length. */ +- if (ftruncate(fd, len) == -1) { ++ if (ftruncate(e->new_fd, len) == -1) { + lu_error_new(error, lu_error_generic, +- _("couldn't write to `%s': %s"), filename, ++ _("couldn't write to `%s': %s"), e->new_filename, + strerror(errno)); + goto err_contents; + } ++ commit = TRUE; + ret = TRUE; + /* Fall through */ + + err_contents: + g_free(contents); +- err_lock: +- lu_util_lock_free(lock); +- err_fd: +- close(fd); +-err_fscreate: +- lu_util_fscreate_restore(fscreate); +- err_filename: +- g_free(filename); ++err_editing: ++ /* Commit/rollback happens here. */ ++ ret = editing_close(e, commit, ret, error); ++err_name: + g_free(name); + return ret; + } +@@ -1344,12 +1500,9 @@ static gboolean + generic_lock(struct lu_module *module, const char *file_suffix, int field, + struct lu_ent *ent, enum lock_op op, struct lu_error **error) + { +- lu_security_context_t fscreate; +- char *filename; ++ struct editing *e; + char *value, *new_value, *name; +- int fd; +- gpointer lock; +- gboolean ret = FALSE; ++ gboolean commit = FALSE, ret = FALSE; + + /* Get the name which keys the entries of interest in the file. */ + g_assert((ent->type == lu_user) || (ent->type == lu_group)); +@@ -1362,33 +1515,14 @@ generic_lock(struct lu_module *module, c + g_assert(module != NULL); + g_assert(ent != NULL); + +- filename = module_filename(module, file_suffix); +- +- if (!lu_util_fscreate_save(&fscreate, error)) +- goto err_filename; +- if (!lu_util_fscreate_from_file(filename, error)) +- goto err_fscreate; +- /* Create a backup of the file. */ +- if (lu_files_create_backup(filename, error) == FALSE) +- goto err_fscreate; +- +- /* Open the file. */ +- fd = open(filename, O_RDWR); +- if (fd == -1) { +- lu_error_new(error, lu_error_open, +- _("couldn't open `%s': %s"), filename, +- strerror(errno)); +- goto err_fscreate; +- } +- +- /* Lock the file. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) +- goto err_fd; ++ e = editing_open(module, file_suffix, error); ++ if (e == NULL) ++ goto err_name; + + /* Read the old value from the file. */ +- value = lu_util_field_read(fd, name, field, error); ++ value = lu_util_field_read(e->new_fd, name, field, error); + if (value == NULL) +- goto err_lock; ++ goto err_editing; + + /* Check that we actually care about this. If there's a non-empty, + * not locked string in there, but it's too short to be a hash, then +@@ -1396,27 +1530,27 @@ generic_lock(struct lu_module *module, c + if (LU_CRYPT_INVALID(value)) { + g_free(value); + ret = TRUE; +- goto err_lock; ++ goto err_editing; + } + + /* Generate a new value for the file. */ + new_value = lock_process(value, op, ent, error); + g_free(value); + if (new_value == NULL) +- goto err_lock; ++ goto err_editing; + + /* Make the change. */ +- ret = lu_util_field_write(fd, name, field, new_value, error); ++ if (lu_util_field_write(e->new_fd, name, field, new_value, error) ++ == FALSE) ++ goto err_editing; ++ commit = TRUE; ++ ret = TRUE; + /* Fall through */ + +-err_lock: +- lu_util_lock_free(lock); +- err_fd: +- close(fd); +-err_fscreate: +- lu_util_fscreate_restore(fscreate); +- err_filename: +- g_free(filename); ++err_editing: ++ /* Commit/rollback happens here. */ ++ ret = editing_close(e, commit, ret, error); ++err_name: + g_free(name); + return ret; + } +@@ -1429,7 +1563,6 @@ generic_is_locked(struct lu_module *modu + char *filename; + char *value, *name; + int fd; +- gpointer lock; + gboolean ret = FALSE; + + /* Get the name of this account. */ +@@ -1454,22 +1587,16 @@ generic_is_locked(struct lu_module *modu + goto err_filename; + } + +- /* Lock the file. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) +- goto err_fd; +- + /* Read the value. */ + value = lu_util_field_read(fd, name, field, error); + if (value == NULL) +- goto err_lock; ++ goto err_fd; + + /* It all comes down to this. */ + ret = value[0] == '!'; + g_free(value); + /* Fall through */ + +-err_lock: +- lu_util_lock_free(lock); + err_fd: + close(fd); + err_filename: +@@ -1624,10 +1751,8 @@ generic_setpass(struct lu_module *module + struct lu_ent *ent, const char *password, gboolean is_shadow, + struct lu_error **error) + { +- lu_security_context_t fscreate; +- char *filename, *value, *name; +- int fd; +- gpointer lock; ++ struct editing *e; ++ char *value, *name; + gboolean ret = FALSE; + + /* Get the name of this account. */ +@@ -1641,34 +1766,14 @@ generic_setpass(struct lu_module *module + g_assert(module != NULL); + g_assert(ent != NULL); + +- filename = module_filename(module, file_suffix); +- +- if (!lu_util_fscreate_save(&fscreate, error)) +- goto err_filename; +- if (!lu_util_fscreate_from_file(filename, error)) +- goto err_fscreate; +- +- /* Create a backup of the file. */ +- if (lu_files_create_backup(filename, error) == FALSE) +- goto err_filename; +- +- /* Open the file. */ +- fd = open(filename, O_RDWR); +- if (fd == -1) { +- lu_error_new(error, lu_error_open, +- _("couldn't open `%s': %s"), filename, +- strerror(errno)); +- goto err_fscreate; +- } +- +- /* Lock the file. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) +- goto err_fd; ++ e = editing_open(module, file_suffix, error); ++ if (e == NULL) ++ goto err_name; + + /* Read the current contents of the field. */ +- value = lu_util_field_read(fd, name, field, error); ++ value = lu_util_field_read(e->new_fd, name, field, error); + if (value == NULL) +- goto err_lock; ++ goto err_editing; + + /* pam_unix uses shadow passwords only if pw_passwd is "x" + (or ##${username}). Make sure to preserve the shadow marker +@@ -1693,9 +1798,9 @@ generic_setpass(struct lu_module *module + else if (g_ascii_strncasecmp(password, LU_CRYPTED, strlen(LU_CRYPTED)) + == 0) { + password = password + strlen(LU_CRYPTED); +- if (strchr(password, ':') != NULL) { ++ if (strpbrk(password, ":\n") != NULL) { + lu_error_new(error, lu_error_invalid_attribute_value, +- _("`:' not allowed in encrypted " ++ _("`:' and `\\n' not allowed in encrypted " + "password")); + goto err_value; + } +@@ -1713,19 +1818,14 @@ generic_setpass(struct lu_module *module + } + + /* Now write our changes to the file. */ +- ret = lu_util_field_write(fd, name, field, password, error); ++ ret = lu_util_field_write(e->new_fd, name, field, password, error); + /* Fall through */ + +- err_value: ++err_value: + g_free(value); +-err_lock: +- lu_util_lock_free(lock); +- err_fd: +- close(fd); +-err_fscreate: +- lu_util_fscreate_restore(fscreate); +- err_filename: +- g_free(filename); ++err_editing: ++ ret = editing_close(e, ret, ret, error); /* Commit/rollback happens here. */ ++err_name: + g_free(name); + return ret; + } +@@ -1802,7 +1902,6 @@ lu_files_enumerate(struct lu_module *mod + const char *pattern, struct lu_error **error) + { + int fd; +- gpointer lock; + GValueArray *ret; + GValue value; + char *buf; +@@ -1824,20 +1923,12 @@ lu_files_enumerate(struct lu_module *mod + return NULL; + } + +- /* Lock the file. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) { +- close(fd); +- g_free(filename); +- return NULL; +- } +- + /* Wrap the file for stdio operations. */ + fp = fdopen(fd, "r"); + if (fp == NULL) { + lu_error_new(error, lu_error_open, + _("couldn't open `%s': %s"), filename, + strerror(errno)); +- lu_util_lock_free(lock); + close(fd); + g_free(filename); + return NULL; +@@ -1873,7 +1964,6 @@ lu_files_enumerate(struct lu_module *mod + + /* Clean up. */ + g_value_unset(&value); +- lu_util_lock_free(lock); + fclose(fp); + g_free(filename); + +@@ -1902,7 +1992,6 @@ lu_files_users_enumerate_by_group(struct + struct lu_error **error) + { + int fd; +- gpointer lock; + GValueArray *ret; + GValue value; + char *buf, grp[CHUNK_SIZE]; +@@ -1927,21 +2016,12 @@ lu_files_users_enumerate_by_group(struct + return NULL; + } + +- /* Lock the passwd file. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) { +- close(fd); +- g_free(pwdfilename); +- g_free(grpfilename); +- return NULL; +- } +- + /* Wrap the descriptor in a stdio FILE. */ + fp = fdopen(fd, "r"); + if (fp == NULL) { + lu_error_new(error, lu_error_open, + _("couldn't open `%s': %s"), pwdfilename, + strerror(errno)); +- lu_util_lock_free(lock); + close(fd); + g_free(pwdfilename); + g_free(grpfilename); +@@ -2000,7 +2080,6 @@ lu_files_users_enumerate_by_group(struct + } + /* Close the file. */ + g_value_unset(&value); +- lu_util_lock_free(lock); + fclose(fp); + + /* Open the group file. */ +@@ -2015,22 +2094,12 @@ lu_files_users_enumerate_by_group(struct + return NULL; + } + +- /* Lock the group file. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) { +- close(fd); +- g_free(pwdfilename); +- g_free(grpfilename); +- g_value_array_free(ret); +- return NULL; +- } +- + /* Wrap the group file in an stdio file. */ + fp = fdopen(fd, "r"); + if (fp == NULL) { + lu_error_new(error, lu_error_open, + _("couldn't open `%s': %s"), grpfilename, + strerror(errno)); +- lu_util_lock_free(lock); + close(fd); + g_free(pwdfilename); + g_free(grpfilename); +@@ -2085,7 +2154,6 @@ lu_files_users_enumerate_by_group(struct + } + + /* Clean up. */ +- lu_util_lock_free(lock); + fclose(fp); + + g_free(pwdfilename); +@@ -2102,7 +2170,6 @@ lu_files_groups_enumerate_by_user(struct + struct lu_error **error) + { + int fd; +- gpointer lock; + GValueArray *ret; + GValue value; + char *buf; +@@ -2126,19 +2193,12 @@ lu_files_groups_enumerate_by_user(struct + goto err_pwdfilename; + } + +- /* Lock it. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) { +- close(fd); +- goto err_pwdfilename; +- } +- + /* Open it so that we can use stdio. */ + fp = fdopen(fd, "r"); + if (fp == NULL) { + lu_error_new(error, lu_error_open, + _("couldn't open `%s': %s"), pwdfilename, + strerror(errno)); +- lu_util_lock_free(lock); + close(fd); + goto err_pwdfilename; + } +@@ -2186,7 +2246,6 @@ lu_files_groups_enumerate_by_user(struct + } + g_free(buf); + } +- lu_util_lock_free(lock); + fclose(fp); + + /* Open the groups file. */ +@@ -2198,19 +2257,12 @@ lu_files_groups_enumerate_by_user(struct + goto err_key; + } + +- /* Lock it. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) { +- close(fd); +- goto err_key; +- } +- + /* Open it so that we can use stdio. */ + fp = fdopen(fd, "r"); + if (fp == NULL) { + lu_error_new(error, lu_error_open, + _("couldn't open `%s': %s"), grpfilename, + strerror(errno)); +- lu_util_lock_free(lock); + close(fd); + goto err_key; + } +@@ -2267,7 +2319,6 @@ lu_files_groups_enumerate_by_user(struct + g_free(key); + g_value_unset(&value); + +- lu_util_lock_free(lock); + fclose(fp); + g_free(pwdfilename); + g_free(grpfilename); +@@ -2291,7 +2342,6 @@ lu_files_enumerate_full(struct lu_module + struct lu_error **error) + { + int fd; +- gpointer lock; + GPtrArray *ret = NULL; + char *buf; + char *key, *filename; +@@ -2311,19 +2361,12 @@ lu_files_enumerate_full(struct lu_module + goto err_filename; + } + +- /* Lock the file. */ +- if ((lock = lu_util_lock_obtain(fd, error)) == NULL) { +- close(fd); +- goto err_filename; +- } +- + /* Wrap the file up in stdio. */ + fp = fdopen(fd, "r"); + if (fp == NULL) { + lu_error_new(error, lu_error_open, + _("couldn't open `%s': %s"), filename, + strerror(errno)); +- lu_util_lock_free(lock); + close(fd); + goto err_filename; + } +@@ -2358,7 +2401,6 @@ lu_files_enumerate_full(struct lu_module + g_free(key); + } + +- lu_util_lock_free(lock); + fclose(fp); + + err_filename: +diff -up libuser-0.60/tests/files_test.py.CVE-2015-3246 libuser-0.60/tests/files_test.py +--- libuser-0.60/tests/files_test.py.CVE-2015-3246 2013-10-12 23:56:08.000000000 +0200 ++++ libuser-0.60/tests/files_test.py 2015-07-08 15:15:14.061544074 +0200 +@@ -262,6 +262,21 @@ class Tests(unittest.TestCase): + e = self.a.initUser('user6_8') + self.assertRaises(RuntimeError, self.a.addUser, e, False, False) + ++ def testUserAdd9(self): ++ # '\n' in field values ++ # libuser.USERPASSWORD not tested because lu_shadow_user_add_prep() ++ # always replaces it by 'x'. libuser.UIDNUMBER not tested because ++ # ent_has_name_and_id() interprets the value as a number. ++ for field in (libuser.USERNAME, libuser.GIDNUMBER, libuser.GECOS, ++ libuser.HOMEDIRECTORY, libuser.LOGINSHELL, ++ libuser.SHADOWPASSWORD, libuser.SHADOWLASTCHANGE, ++ libuser.SHADOWMIN, libuser.SHADOWMAX, ++ libuser.SHADOWWARNING, libuser.SHADOWINACTIVE, ++ libuser.SHADOWEXPIRE, libuser.SHADOWFLAG): ++ e = self.a.initUser('user_6_9' + field) ++ e[field] = str(e[field][0]) + '\nx' ++ self.assertRaises(RuntimeError, self.a.addUser, e, False, False) ++ + def testUserMod1(self): + # A minimal case + e = self.a.initUser('user7_1') +@@ -421,6 +436,26 @@ class Tests(unittest.TestCase): + e[libuser.USERNAME] = 'user7_7' + self.assertRaises(RuntimeError, self.a.modifyUser, e, False) + ++ def testUserMod8(self): ++ # '\n' in field values ++ # libuser.USERPASSWORD not tested because lu_shadow_user_add_prep() ++ # always replaces it by 'x'. libuser.UIDNUMBER not tested because ++ # ent_has_name_and_id() interprets the value as a number. ++ for field in (libuser.USERNAME, libuser.USERPASSWORD, libuser.GIDNUMBER, ++ libuser.GECOS, libuser.HOMEDIRECTORY, libuser.LOGINSHELL, ++ libuser.SHADOWPASSWORD, libuser.SHADOWLASTCHANGE, ++ libuser.SHADOWMIN, libuser.SHADOWMAX, ++ libuser.SHADOWWARNING, libuser.SHADOWINACTIVE, ++ libuser.SHADOWEXPIRE, libuser.SHADOWFLAG): ++ e = self.a.initUser('user7_9' + field) ++ self.a.addUser(e, False, False) ++ del e ++ e = self.a.lookupUserByName('user7_9' + field) ++ self.assertIsNotNone(e) ++ self.assertNotIn('\n', str(e[field][0])) ++ e[field] = str(e[field][0]) + '\nx' ++ self.assertRaises(RuntimeError, self.a.modifyUser, e, False) ++ + def testUserDel(self): + e = self.a.initUser('user8_1') + self.a.addUser(e, False, False) +@@ -619,6 +654,22 @@ class Tests(unittest.TestCase): + crypted = crypt.crypt('a:b', e[libuser.SHADOWPASSWORD][0]) + self.assertEqual(e[libuser.SHADOWPASSWORD], [crypted]) + ++ def testUserSetpass5(self): ++ # '\n' in field value ++ e = self.a.initUser('user12_5') ++ self.a.addUser(e, False, False) ++ del e ++ e = self.a.lookupUserByName('user12_5') ++ self.assertNotIn('\n', e[libuser.SHADOWPASSWORD][0]) ++ self.assertRaises(SystemError, self.a.setpassUser, e, 'a\nb', True) ++ self.a.setpassUser(e, 'a\nb', False) ++ del e ++ e = self.a.lookupUserByName('user12_5') ++ self.assertEqual(e[libuser.SHADOWPASSWORD][0][:3], '$1$') ++ self.assertNotIn('\n', e[libuser.SHADOWPASSWORD][0]) ++ crypted = crypt.crypt('a\nb', e[libuser.SHADOWPASSWORD][0]) ++ self.assertEqual(e[libuser.SHADOWPASSWORD], [crypted]) ++ + def testUserRemovepass(self): + e = self.a.initUser('user13_1') + e[libuser.SHADOWPASSWORD] = '03dgZm5nZvqOc' +@@ -884,6 +935,20 @@ class Tests(unittest.TestCase): + e = self.a.initGroup('group21_5') + self.assertRaises(RuntimeError, self.a.addGroup, e) + ++ def testGroupAdd6(self): ++ # '\n' in field values ++ # libuser.GROUPPASSWORD not tested because lu_shadow_group_add_prep() ++ # always replaces it by 'x'. libuser.GIDNUMBER not tested because ++ # ent_has_name_and_id() interprets the value as a number. ++ for field in (libuser.GROUPNAME, libuser.SHADOWPASSWORD, ++ libuser.MEMBERNAME, libuser.ADMINISTRATORNAME): ++ e = self.a.initGroup('group_21_6' + field) ++ if e.has_key(field): ++ e[field] = str(e[field][0]) + '\nx' ++ else: ++ e[field] = field + '\nx' ++ self.assertRaises(RuntimeError, self.a.addGroup, e) ++ + def testGroupMod1(self): + # A minimal case + e = self.a.initGroup('group22_1') +@@ -997,6 +1062,25 @@ class Tests(unittest.TestCase): + e[libuser.GROUPNAME] = 'group22_6' + self.assertRaises(RuntimeError, self.a.modifyGroup, e) + ++ def testGroupMod7(self): ++ # '\n' in field values ++ # libuser.GIDNUMBER not tested because ent_has_name_and_id() interprets ++ # the value as a number. ++ for field in (libuser.GROUPNAME, libuser.GROUPPASSWORD, ++ libuser.SHADOWPASSWORD, libuser.MEMBERNAME, ++ libuser.ADMINISTRATORNAME): ++ e = self.a.initGroup('group22_8' + field) ++ self.a.addGroup(e) ++ del e ++ e = self.a.lookupGroupByName('group22_8' + field) ++ self.assertIsNotNone(e) ++ if e.has_key(field): ++ self.assertNotIn('\n', str(e[field][0])) ++ e[field] = str(e[field][0]) + '\nx' ++ else: ++ e[field] = field + '\nx' ++ self.assertRaises(RuntimeError, self.a.modifyGroup, e) ++ + def testGroupDel(self): + e = self.a.initGroup('group23_1') + self.a.addGroup(e) +@@ -1190,6 +1274,22 @@ class Tests(unittest.TestCase): + crypted = crypt.crypt('a:b', e[libuser.SHADOWPASSWORD][0]) + self.assertEqual(e[libuser.SHADOWPASSWORD], [crypted]) + ++ def testGroupSetpass4(self): ++ # '\n' in field value ++ e = self.a.initGroup('group27_5') ++ self.a.addGroup(e) ++ del e ++ e = self.a.lookupGroupByName('group27_5') ++ self.assertNotIn('\n', e[libuser.SHADOWPASSWORD][0]) ++ self.assertRaises(SystemError, self.a.setpassGroup, e, 'a\nb', True) ++ self.a.setpassGroup(e, 'a\nb', False) ++ del e ++ e = self.a.lookupGroupByName('group27_5') ++ self.assertEqual(e[libuser.SHADOWPASSWORD][0][:3], '$1$') ++ self.assertNotIn('\n', e[libuser.SHADOWPASSWORD][0]) ++ crypted = crypt.crypt('a\nb', e[libuser.SHADOWPASSWORD][0]) ++ self.assertEqual(e[libuser.SHADOWPASSWORD], [crypted]) ++ + def testGroupRemovepass(self): + e = self.a.initGroup('group28_1') + e[libuser.SHADOWPASSWORD] = '07Js7N.eEhbgs' diff --git a/SPECS/libuser.spec b/SPECS/libuser.spec new file mode 100644 index 0000000..6d514a4 --- /dev/null +++ b/SPECS/libuser.spec @@ -0,0 +1,927 @@ +%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")} + +Name: libuser +Version: 0.60 +Release: 9%{?dist} +Group: System Environment/Base +License: LGPLv2+ +URL: https://fedorahosted.org/libuser/ +Source: https://fedorahosted.org/releases/l/i/libuser/libuser-%{version}.tar.xz +# https://bugzilla.redhat.com/show_bug.cgi?id=1480537 +Source1: libuser-0.60-ja.po +Patch0: libuser-CVE-2015-3246.patch +BuildRequires: glib2-devel, linuxdoc-tools, pam-devel, popt-devel, python2-devel +BuildRequires: cyrus-sasl-devel, libselinux-devel, openldap-devel +# To make sure the configure script can find it +BuildRequires: nscd +# For %%check +BuildRequires: openldap-clients, openldap-servers, openssl +BuildRequires: gettext +Summary: A user and group account administration library + +%description +The libuser library implements a standardized interface for manipulating +and administering user and group accounts. The library uses pluggable +back-ends to interface to its data sources. + +Sample applications modeled after those included with the shadow password +suite are included. + +%package devel +Group: Development/Libraries +Summary: Files needed for developing applications which use libuser +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: glib2-devel%{?_isa} + +%description devel +The libuser-devel package contains header files, static libraries, and other +files useful for developing applications with libuser. + +%package python +Summary: Python bindings for the libuser library +Group: Development/Libraries +Requires: libuser%{?_isa} = %{version}-%{release} + +%description python +The libuser-python package contains the Python bindings for +the libuser library, which provides a Python API for manipulating and +administering user and group accounts. + +%prep +%setup -q + +%patch0 -p1 -b .CVE-2015-3246 +cp %{SOURCE1} po/ja.po + +%build +%configure --with-selinux --with-ldap --with-html-dir=%{_datadir}/gtk-doc/html +make +make -C po ja.gmo # (make all) only rebuilds .gmo files if the .pot file is updated, regardless of po/ja.po changes + +%install +make install DESTDIR=$RPM_BUILD_ROOT INSTALL='install -p' + +%find_lang %{name} + +%check + +make check || { cat test-suite.log; false; } + +# Verify that all python modules load, just in case. +LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_libdir}:${LD_LIBRARY_PATH} +export LD_LIBRARY_PATH +cd $RPM_BUILD_ROOT/%{python_sitearch} +python -c "import libuser" + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files -f %{name}.lang +%doc AUTHORS COPYING NEWS README TODO docs/*.txt +%config(noreplace) %{_sysconfdir}/libuser.conf + +%attr(0755,root,root) %{_bindir}/* +%{_libdir}/*.so.* +%dir %{_libdir}/%{name} +%{_libdir}/%{name}/*.so +%attr(0755,root,root) %{_sbindir}/* +%{_mandir}/man1/* +%{_mandir}/man5/* + +%exclude %{_libdir}/*.la +%exclude %{_libdir}/%{name}/*.la + +%files python +%doc python/modules.txt +%{python_sitearch}/*.so +%exclude %{python_sitearch}/*.la + +%files devel +%{_includedir}/libuser +%{_libdir}/*.so +%{_libdir}/pkgconfig/* +%{_datadir}/gtk-doc/html/* + +%changelog +* Mon Jan 15 2018 Miloslav Trmač - 0.60-9 +- Update Japanese translation + Resolves: #1480537 + +* Tue Dec 5 2017 Miloslav Trmač - 0.60-8 +- Update Japanese translation + Resolves: #1480537 + +* Wed Jul 8 2015 Miloslav Trmač - 0.60-7 +- Update CVE-2015-3246 patch based on review comments + Resolves: #1235520 + +* Fri Jun 26 2015 Miloslav Trmač - 0.60-6 +- Fix CVE-2015-3246 + Resolves: #1235520 + +* Fri Jan 24 2014 Daniel Mach - 0.60-5 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 0.60-4 +- Mass rebuild 2013-12-27 + +* Tue Oct 15 2013 Miloslav Trmač - 0.60-3 +- Fix the -2 change, %%check should fail on test suite failure +- Drop an upstreamed patch + +* Mon Oct 14 2013 Miloslav Trmač - 0.60-2 +- Include test suite output in build log on failure + +* Mon Oct 14 2013 Miloslav Trmač - 0.60-1 +- Update to libuser-0.60 + Resolves: #1008933 + +* Thu Jun 27 2013 Miloslav Trmač - 0.59-2 +- Drop BuildRequires: fakeroot and skip the test that needs it + Resolves: #975888 + +* Thu Mar 28 2013 Miloslav Trmač - 0.59-1 +- Update to libuser-0.59 (CVE-2012-5630, CVE-2012-5644) + Resolves: #928846 + +* Mon Feb 4 2013 Miloslav Trmač - 0.58-2 +- Always use secure_getenv() or __secure_getenv(), fail build if neither is + available. Patch by Viktor Hercinger . + +* Thu Nov 8 2012 Miloslav Trmač - 0.58-1 +- Update to libuser-0.58 + Resolves: #844140, #854236 + +* Mon Sep 24 2012 Miloslav Trmač - 0.57.7-1 +- Update to libuser-0.57.7 + +* Tue Aug 21 2012 Miloslav Trmač - 0.57.6-3 +- Drop no longer necessary %%clean and %%defattr commands. + +* Thu Jul 19 2012 Fedora Release Engineering - 0.57.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Thu Mar 22 2012 Miloslav Trmač - 0.57.6-1 +- Update to libuser-0.57.6 + Resolves: #803840 + +* Sat Mar 3 2012 Miloslav Trmač - 0.57.5-1 +- Update to libuser-0.57.5 +- BuildRequires: openssl, the testsuite needs /usr/bin/openssl + +* Fri Feb 10 2012 Miloslav Trmač - 0.57.4-1 +- Update to libuser-0.57.4 + Resolves: #788521 + +* Fri Jan 13 2012 Fedora Release Engineering - 0.57.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Oct 4 2011 Miloslav Trmač - 0.57.3-2 +- Wait up to 30 seconds for slapd to start in the test suite + +* Tue Oct 4 2011 Miloslav Trmač - 0.57.3-1 +- Update to libuser-0.57.3 + Resolves: #717116, #724986 + +* Thu Mar 31 2011 Miloslav Trmač - 0.57.2-1 +- Update to libuser-0.57.2 + Resolves: #671494 +- Reenable (make check) + +* Tue Feb 08 2011 Fedora Release Engineering - 0.57.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Fri Feb 4 2011 Miloslav Trmač - 0.57.1-4 +- Use %%{?_isa} in Requires: + +* Fri Jan 21 2011 Miloslav Trmač - 0.57.1-3 +- Disable (make check) to allow parallel 32-bit and 64-bit builds + +* Thu Jan 20 2011 Miloslav Trmač - 0.57.1-2 +- Don't default commonName to gecos if it is empty + Resolves: #670151 + +* Fri Jan 14 2011 Miloslav Trmač - 0.57.1-1 +- Update to libuser-0.57.1 + Resolves: #668855 + +* Mon Jan 10 2011 Miloslav Trmač - 0.57-1 +- Update to libuser-0.57 + Resolves: #497333 #610172 + +* Wed Sep 29 2010 Miloslav Trmač - 0.56.18-2 +- Handle matchpathcon() failing with ENOENT + Resolves: #631717 + +* Tue Sep 14 2010 Miloslav Trmač - 0.56.18-1 +- Update to libuser-0.56.18 + +* Wed Sep 1 2010 Miloslav Trmač - 0.56.17-2 +- Change default crypt_style to sha512 + Resolves: #629001 + +* Thu Aug 26 2010 Miloslav Trmač - 0.56.17-1 +- Update to libuser-0.56.17 + +* Wed Jul 21 2010 David Malcolm - 0.56.16-3 +- Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild + +* Fri Jul 2 2010 Miloslav Trmač - 0.56.16-2 +- Provide LU_VALUE_INVALID_ID and id_t validation in the Python module + Resolves: #610838 + +* Thu Mar 25 2010 Miloslav Trmač - 0.56.16-1 +- Update to libuser-0.56.16. + +* Thu Mar 4 2010 Miloslav Trmač - 0.56.15-1 +- Update to libuser-0.56.15. +- Drop no longer necessary references to BuildRequires + +* Mon Feb 8 2010 Miloslav Trmač - 0.56.14-1 +- Update to libuser-0.56.14. + +* Tue Jan 5 2010 Miloslav Trmač - 0.56.13-2 +- s/%%define/%%global/ + +* Fri Dec 11 2009 Miloslav Trmač - 0.56.13-1 +- Update to libuser-0.56.13. + Resolves: #251951 + Resolves: #454079 + Resolves: #456373 + Resolves: #456382 + Resolves: #530513 + +* Fri Oct 2 2009 Miloslav Trmač - 0.56.12-1 +- Update to libuser-0.56.12. + +* Mon Sep 14 2009 Miloslav Trmač - 0.56.11-1 +- Update to libuser-0.56.11. + Resolves: #454091 + Resolves: #456267 + Resolves: #456270 + Resolves: #487129 + +* Thu Jul 30 2009 Miloslav Trmač - 0.56.10-3 +- Fix nscd cache invalidation + Resolves: #506628 +- Preserve timestamps during (make install) + +* Sat Jul 25 2009 Fedora Release Engineering - 0.56.10-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Wed Apr 15 2009 Miloslav Trmač - 0.56.10-1 +- Update to libuser-0.56.10. + +* Wed Feb 25 2009 Fedora Release Engineering - 0.56.9-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Sat Nov 29 2008 Ignacio Vazquez-Abrams - 0.56.9-2 +- Rebuild for Python 2.6 + +* Wed Apr 9 2008 Miloslav Trmač - 0.56.9-1 +- Update to libuser-0.56.9. + +* Sat Feb 23 2008 Miloslav Trmač - 0.56.8-1 +- New home page at https://fedorahosted.org/libuser/ . + +* Tue Feb 19 2008 Fedora Release Engineering - 0.56.7-2 +- Autorebuild for GCC 4.3 + +* Wed Jan 9 2008 Miloslav Trmač - 0.56.7-1 +- Add support for SHA256 and SHA512 in password hashes + Related: #173583 +- Fix file locking on some architectures +- Rename sr@Latn.po to sr@latin.po + Resolves: #426584 +- Address issues from a review by Jason Tibbitts: + - Remove default.-c, moving the provided functions to libuser proper + - Remove the WITH_SELINUX build option + - Move Python library test to %%check + Resolves: #226054 + +* Mon Jan 07 2008 Jason L Tibbitts III - 0.56.6-4 +- Add the usual "there is no upstream" notice. + +* Tue Dec 04 2007 Release Engineering - 0.56.6-4 + - Rebuild for openldap bump + +* Tue Dec 4 2007 Miloslav Trmač - 0.56.6-3 +- Rebuild with openldap-2.4. + +* Wed Oct 31 2007 Miloslav Trmač - 0.56.6-2 +- Fix uninitialized memory usage when SELinux is disabled + +* Thu Oct 25 2007 Miloslav Trmač - 0.56.6-1 +- Set SELinux file contexts when creating home directories, preserve them when + moving home directories + Resolves: #351201 + +* Thu Oct 11 2007 Miloslav Trmač - 0.56.5-1 +- Work around spurious error messages when run against the Fedora Directory + server +- Fix error reporting when creating home directories and creating/removing mail + spool files + Resolves: #318121 + +* Wed Sep 5 2007 Miloslav Trmač - 0.56.4-3 +- s/popt/popt-devel/ in BuildRequires + Resolves: #277541 + +* Wed Aug 8 2007 Miloslav Trmač - 0.56.4-2 +- Split the Python module to a separate subpackage (original patch by Yanko + Kaneti) +- Update the License: tag + +* Fri Jun 15 2007 Miloslav Trmač - 0.56.4-1 +- Update the last password change date field when changing passwords + Resolves: #243854 + +* Sat Jun 9 2007 Miloslav Trmač - 0.56.3-1 +- Allow specifying a SASL mechanism (original patch by Simo Sorce) + Resolves: #240904 + +* Thu Apr 19 2007 Miloslav Trmac - 0.56.2-1 +- New release with updated translations + +* Fri Feb 23 2007 Miloslav Trmac - 0.56.1-1 +- When changing passwords, only silently ignore know shadow markers, not all + invalid hashes + Resolves: #225495 + +* Sat Feb 17 2007 Miloslav Trmac - 0.56-1 +- Tighten the API and implementation to avoid corrupting number-like strings; + the module interface ABI has changed + Resolves: #226976 + +* Sat Jan 6 2007 Jeremy Katz - 0.55-2 +- Fix inconsistent PyObject/PyMem usage (#220679) + +* Sun Dec 10 2006 Miloslav Trmac - 0.55-1 +- Update to support the 64-bit API of Python 2.5 +- Drop the quota library and Python module + +* Thu Dec 7 2006 Jeremy Katz - 0.54.8-2 +- rebuild against python2.5 +- follow python packaging guidelines + +* Thu Nov 2 2006 Miloslav Trmac - 0.54.8-1 +- Add importing of HOME from default/useradd + Related: #204707 + +* Sun Oct 01 2006 Jesse Keating - 0.54.7-2 +- rebuilt for unwind info generation, broken in gcc-4.1.1-21 + +* Mon Sep 25 2006 Miloslav Trmac - 0.54.7-1 +- New release with updated translations + +* Wed Jul 12 2006 Jesse Keating - 0.54.6-2.1 +- rebuild + +* Wed Jun 7 2006 Miloslav Trmac - 0.54.6-2 +- Configure without --enable-gtk-doc to fix multilib conflict (#192715) + +* Mon May 1 2006 Miloslav Trmac - 0.54.6-1 +- Fix bugs in handling of invalid lines in the files and shadow modules +- Fix pattern matching in lu_*_enumerate_full in the files and shadow modules +- Add more error reporting, return non-zero exit status on error from utils +- Use the skeleton directory specified in libuser.conf by Python + admin.createHome and admin.addUser, add parameter skeleton= to admin.addUser + (#189984) + +* Tue Feb 21 2006 Miloslav Trmac - 0.54.5-1 +- Fix multilib conflict on libuser.conf.5 + +* Mon Feb 13 2006 Miloslav Trmac - 0.54.4-1 +- New release with updated translations + +* Fri Feb 10 2006 Jesse Keating - 0.54.3-1.2.1 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 0.54.3-1.2 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Fri Dec 2 2005 Miloslav Trmac - 0.54.3-1 +- Fix crash in lpasswd when user is not specified (#174801) + +* Fri Nov 11 2005 Miloslav Trmac - 0.54.2-1 +- Avoid using deprecated openldap functions + +* Fri Nov 11 2005 Miloslav Trmac - 0.54.1-2 +- Rebuild with newer openldap + +* Tue Oct 11 2005 Miloslav Trmac - 0.54.1-1 +- Support importing of configuration from shadow-utils (/etc/login.defs and + /etc/default/useradd) +- Add libuser.conf(5) man page + +* Wed Oct 5 2005 Matthias Clasen - 0.54-2 +- Use gmodule-no-export in the .pc file + +* Tue Sep 13 2005 Miloslav Trmac - 0.54-1 +- Make sure attributes with no values can never appear +- Fix crash in the "files" module when an attribute is missing +- Use hidden visibility for internal functions, remove them from + libuser/user_private.h; this changes module interface ABI + +* Wed Jun 8 2005 Miloslav Trmac - 0.53.8-1 +- Permit "portable" user and group names as defined by SUSv3, plus trailing $ + (#159452) +- Don't build static libraries + +* Sat Apr 30 2005 Miloslav Trmac - 0.53.7-1 +- Rebuild with updated translations, add missing translations. + +* Sun Apr 24 2005 Miloslav Trmac - 0.53.6-1 +- Allow empty configuration values (#155402) + +* Fri Apr 15 2005 Miloslav Trmac - 0.53.5-1 +- Ignore nss_compat lines in the "files" module (#154651) +- Autodetect Python version (#154096) +- Add BuildRequires: libselinux-devel, s/BuildPrereq/BuildRequires/ + +* Wed Apr 6 2005 Miloslav Trmac - 0.53.4-1 +- Fix adding objectclasses to existing LDAP entries (#152960) + +* Wed Mar 30 2005 Miloslav Trmac - 0.53.3-2 +- Add Requires: glib2-devel to libuser-devel (#152501) +- Run ldconfig using %%post{,un} -p to let RPM play tricks + +* Sat Mar 5 2005 Miloslav Trmac - 0.53.3-1 +- Don't silently ignore some I/O errors +- Don't include a Cyrus SASL v1 header file when libldap links to v2 (#150046) +- Rebuild with gcc 4 + +* Mon Jan 17 2005 Miloslav Trmac - 0.53.2-1 +- Important bug fixes in lchage, lgroupmod, lnewusers and lusermod +- Minor bug fixes in lpasswd and luseradd +- Add man pages for the utilities (#61673) + +* Mon Dec 13 2004 Miloslav Trmac - 0.53.1-1 +- Export UT_NAMESIZE from to Python (#141273) + +* Sun Nov 14 2004 Miloslav Trmac - 0.53-1 +- Support UID and GID values larger than LONG_MAX (#124967) +- Fix updating of groups after user renaming in lusermod +- Allow setting a shadow password even if the current shadow password is + invalid (#131180) +- Add lu_{user,group}_unlock_nonempty (#86414); module interface ABI has + changed +- Miscellaneous bug and memory leak fixes + +* Mon Nov 8 2004 Jeremy Katz - 0.52.6-2 +- rebuild against python 2.4 + +* Tue Nov 2 2004 Miloslav Trmac - 0.52.6-1 +- Make error reporting more consistent, more verbose and always on stderr + (partly #133861, original patch by Pawel Salek) +- Mark strings previously blocked by string freeze for translation + +* Tue Oct 12 2004 Miloslav Trmac - 0.52.5-1 +- Fix home directory renaming in ADMIN.modifyUser (#135280) +- Further Python reference counting fixes + +* Sun Oct 10 2004 Miloslav Trmac - 0.52.4-1 +- Fix memory leaks (#113730) +- Build with updated translations + +* Wed Sep 29 2004 Miloslav Trmac - 0.52.3-1 +- Fix compilation without libuser headers already installed (#134085) + +* Tue Sep 28 2004 Miloslav Trmac - 0.52.2-1 +- Allow LDAP connection using ldaps, custom ports or without TLS (original + patch from Pawel Salek). + +* Mon Sep 27 2004 Miloslav Trmac - 0.52.1-1 +- Fix freecon() of uninitialized value in files/shadow module + +* Mon Sep 27 2004 Miloslav Trmac - 0.52-1 +- Usable LDAP backend (#68052, #99435, #130404) +- Miscellaneous bug fixes + +* Fri Sep 24 2004 Miloslav Trmac - 0.51.12-1 +- Don't claim success and exception at the same time (#133479) +- LDAP fixes, second round +- Various other bugfixes + +* Thu Sep 23 2004 Miloslav Trmac - 0.51.11-1 +- Allow documented optional arguments in Python + ADMIN.{addUser,modifyUser,deleteUser} (#119812) +- Add man pages for lchfn and lchsh +- LDAP fixes, first round +- Avoid file conflict on multilib systems +- Call ldconfig correctly + +* Fri Sep 3 2004 Miloslav Trmac - 0.51.10-1 +- Don't attempt to lookup using original entity name after entity + modification (rename in particular) (#78376, #121252) +- Fix copying of symlinks from /etc/skel (#87572, original patch from gLaNDix) +- Make --enable-quota work, and fix the quota code to at least compile (#89114) +- Fix several bugs (#120168, original patch from Steve Grubb) +- Don't hardcode python version in spec file (#130952, from Robert Scheck) +- Properly integrate the SELinux patch, it should actually be used now, even + though it was "enabled" since 0.51.7-6 + +* Tue Aug 31 2004 Miloslav Trmac - 0.51.9-1 +- Fix various typos +- Document library interfaces +- Build all shared libraries with -fPIC (#72536) + +* Wed Aug 25 2004 Miloslav Trmac - 0.51.8-1 +- Update to build with latest autotools and gtk-doc +- Update ALL_LINGUAS and POTFILES.in +- Rebuild to depend on newer openldap + +* Mon Jan 26 2004 Dan Walsh 0.51.7-7 +- fix is_selinux_enabled call + +* Sun Dec 14 2003 Jeremy Katz 0.51.7-6 +- rebuild against python 2.3 +- enable SELinux + +* Mon Sep 08 2003 Dan Walsh 0.51.7-5 +- Turn off SELinux + +* Wed Aug 06 2003 Dan Walsh 0.51.7-3 +- Add SELinux support + +* Wed Feb 19 2003 Nalin Dahyabhai 0.51.7-1 +- ldap: set error codes correctly when we encounter failures initializing +- don't double-close modules which fail initialization +- ldap: don't set an error in cases where one is already set + +* Tue Feb 18 2003 Nalin Dahyabhai 0.51.6-1 +- use a crypt salt consistent with the defaults/crypt_style setting when + setting new passwords (#79337) + +* Thu Feb 6 2003 Nalin Dahyabhai 0.51.5-2 +- rebuild + +* Wed Feb 5 2003 Nalin Dahyabhai 0.51.5-1 +- expose lu_get_first_unused_id() as a package-private function +- provide libuser.ADMIN.getFirstUnusedUid and libuser.ADMIN.getFirstUnusedGid + in python + +* Thu Dec 19 2002 Nalin Dahyabhai 0.51.4-1 +- fix not freeing resources properly in files.c(generic_is_locked), spotted by + Zou Pengcheng + +* Wed Dec 11 2002 Nalin Dahyabhai 0.51.2-1 +- degrade gracefully +- build with --with-pic and -fPIC +- remove unpackaged man page + +* Tue Aug 27 2002 Nalin Dahyabhai 0.51.1-2 +- translation updates + +* Wed Jul 24 2002 Nalin Dahyabhai 0.51.1-1 +- doc updates -- cvs tree moved +- language updates +- disallow weird characters in account names + +* Sun May 26 2002 Tim Powers +- automated rebuild + +* Mon May 20 2002 Nalin Dahyabhai 0.51-1 +- files: ignore blank lines in files +- libuser: disallow creation of accounts with names containing whitespace, + control characters, or non-ASCII characters + +* Tue Apr 16 2002 Nalin Dahyabhai 0.50.2-1 +- refresh translations +- fix a heap-corruption bug in the python bindings + +* Mon Apr 15 2002 Nalin Dahyabhai 0.50-1 +- bump version +- refresh translations + +* Thu Mar 14 2002 Nalin Dahyabhai 0.49.102-1 +- ldap: cache an entity's dn in the entity structure to try to speed things up + +* Mon Mar 11 2002 Nalin Dahyabhai 0.49.101-3 +- rebuild in new environment + +* Thu Mar 7 2002 Nalin Dahyabhai 0.49.101-2 +- add missing buildreqs on cyrus-sasl-devel and openldap-devel (#59456) +- translation refresh + +* Fri Mar 1 2002 Nalin Dahyabhai 0.49.101-1 +- fix python bindings of enumerateFull functions +- adjust prompter wrapping to not error out on successful returns + +* Thu Feb 28 2002 Nalin Dahyabhai 0.49.100-1 +- be more careful about printing error messages +- fix refreshing after adding of accounts +- ldap: try to use a search to convert names to DNs, and only fall back to + guessing if it turns up nothing +- files: fix an off-by-one in removal of entries + +* Mon Feb 25 2002 Nalin Dahyabhai 0.49.99-1 +- refresh translations +- fix admin() constructor comments in the python module + +* Thu Feb 21 2002 Nalin Dahyabhai 0.49.98-1 +- automatically refresh entities after add, modify, setpass, removepass, + lock, and unlock operations +- remove debug spewage when creating and removing mail spools +- files: fix saving of multi-valued attributes +- rename MEMBERUID attribute for groups to MEMBERNAME + +* Wed Feb 20 2002 Nalin Dahyabhai 0.49.97-1 +- files: fix bug in removals +- ldap: revert attempts at being smart at startup time, because it makes UIs + very messy (up the three whole dialogs just to start the ldap stuff!) + +* Sat Feb 16 2002 Nalin Dahyabhai 0.49.96-1 +- fix thinko in dispatch routines + +* Wed Feb 13 2002 Nalin Dahyabhai 0.49.95-1 +- lgroupmod: fix thinko + +* Thu Jan 31 2002 Nalin Dahyabhai 0.49.94-2 +- rebuild in new environment + +* Tue Jan 29 2002 Nalin Dahyabhai 0.49.93-1 +- move shadow initialization for groups to the proper callback +- rework locking in the files module to not require that files be writable + +* Tue Jan 29 2002 Nalin Dahyabhai +- expose lu_strerror() +- add various typedefs for types used by the library + +* Mon Jan 28 2002 Nalin Dahyabhai 0.49.92-1 +- add removepass() functions + +* Thu Jan 24 2002 Nalin Dahyabhai +- lchfn,lchsh,lpasswd - reorder PAM authentication calls +- include API docs in the package + +* Thu Jan 24 2002 Nalin Dahyabhai 0.49.91-1 +- ldap: finish port to new API +- sasl: finish port to new API (needs test) +- libuser: don't commit object changes before passing data to service + functions which might need differing data sets to figure out what to + change (for example, ldap) + +* Thu Jan 17 2002 Nalin Dahyabhai 0.49.90-1 +- bind the internal mail spool creation/removal functions for python + +* Wed Jan 16 2002 Nalin Dahyabhai +- renamed the python module +- revamped internals to use gobject's gvalues and gvaluearrays instead of + glists of cached strings +- add enumeration-with-data functions to the C library + +* Mon Jan 07 2002 Florian La Roche +- require linuxdoc-tools instead of sgml-tools for rawhide + +* Tue Nov 13 2001 Nalin Dahyabhai +- fixup build files to allow building for arbitrary versions of python + +* Wed Aug 29 2001 Nalin Dahyabhai 0.32-1 +- link the python module against libpam +- attempt to import the python modules at build-time to verify dependencies + +* Tue Aug 28 2001 Nalin Dahyabhai 0.31-1 +- fix a file-parsing bug that popped up in 0.29's mmap modifications + +* Mon Aug 27 2001 Nalin Dahyabhai 0.30-1 +- quotaq: fix argument order when reading quota information +- user_quota: set quota grace periods correctly +- luseradd: never create home directories for system accounts + +* Tue Aug 21 2001 Nalin Dahyabhai +- add da translation files +- update translations + +* Tue Aug 21 2001 Nalin Dahyabhai 0.29-1 +- add an explicit build dependency on jade (for the docs) + +* Mon Aug 20 2001 Nalin Dahyabhai +- HUP nscd on modifications +- userutil.c: mmap files we're reading for probable speed gain +- userutil.c: be conservative with the amount of random data we read +- docs fixes + +* Wed Aug 15 2001 Nalin Dahyabhai 0.28-1 +- apps: print usage on errors +- lnewusers.c: initialize groups as groups, not users +- lnewusers.c: set passwords for new accounts +- luseradd.c: accept group names in addition to IDs for the -g flag +- luseradd.c: allow the primary GID to be a preexisting group + +* Tue Aug 14 2001 Nalin Dahyabhai 0.27-1 +- add ko translation files +- files.c: fix a heap corruption bug in lock/unlock (#51750) +- files.c: close a memory leak in reading of files + +* Mon Aug 13 2001 Nalin Dahyabhai +- files.c: remove implementation limits on lengths of lines + +* Thu Aug 9 2001 Nalin Dahyabhai 0.26-1 +- lusermod: change user name in groups the user is a member of during renames +- lgroupmod: change primary GID for users who are in the group during renumbers +- ldap.c: handle new attributes more gracefully if possible +- add ru translation files + +* Tue Aug 7 2001 Nalin Dahyabhai 0.25.1-1 +- rename the quota source files to match the library, which clears up a + file conflict with older quota packages +- add ja translation files + +* Thu Aug 2 2001 Nalin Dahyabhai +- add lu_ent_clear_all() function + +* Thu Aug 2 2001 Nalin Dahyabhai 0.25-1 +- close up some memory leaks +- add the ability to include resident versions of modules in the library + +* Wed Aug 1 2001 Nalin Dahyabhai 0.24-4 +- fix incorrect Py_BuildValue invocation in python module + +* Tue Jul 31 2001 Nalin Dahyabhai 0.24-3 +- stop leaking descriptors in the files module +- speed up user creation by reordering some checks for IDs being in use +- update the shadowLastChanged attribute when we set a password +- adjust usage of getXXXXX_r where needed +- fix assorted bugs in python binding which break prompting + +* Mon Jul 30 2001 Nalin Dahyabhai 0.23-1 +- install sv translation +- make lpasswd prompt for passwords when none are given on the command line +- make sure all user-visible strings are marked for translation +- clean up some user-visible strings +- require PAM authentication in lchsh, lchfn, and lpasswd for non-networked modules + +* Fri Jul 27 2001 Nalin Dahyabhai +- print uids and gids of users and names in lid app +- fix tree traversal in users_enumerate_by_group and groups_enumerate_by_users +- implement enumerate_by_group and enumerate_by_user in ldap module +- fix id-based lookups in the ldap module +- implement islocked() method in ldap module +- implement setpass() method in ldap module +- add lchfn and lchsh apps +- add %%d substitution to libuser.conf + +* Thu Jul 26 2001 Nalin Dahyabhai 0.21-1 +- finish adding a sasldb module which manipulates a sasldb file +- add users_enumerate_by_group and groups_enumerate_by_users + +* Wed Jul 25 2001 Nalin Dahyabhai +- luserdel: remove the user's primary group if it has the same name as + the user and has no members configured (-G disables) +- fixup some configure stuff to make libuser.conf get generated correctly + even when execprefix isn't specified + +* Tue Jul 24 2001 Nalin Dahyabhai 0.20-1 +- only call the auth module when setting passwords (oops) +- use GTrees instead of GHashTables for most internal tables +- files: complain properly about unset attributes +- files: group passwords are single-valued, not multiple-valued +- add lpasswd app, make sure all apps start up popt with the right names + +* Mon Jul 23 2001 Nalin Dahyabhai 0.18-1 +- actually make the new optional arguments optional +- fix lu_error_new() to actually report errors right +- fix part of the python bindings +- include tools in the binary package again +- fixup modules so that password-changing works right again +- add a "key" field to prompt structures for use by apps which like to + cache these things +- add an optional "mvhomedir" argument to userModify (python) + +* Fri Jul 20 2001 Nalin Dahyabhai 0.16.1-1 +- finish home directory population +- implement home directory moving +- change entity get semantics in the python bindings to allow default values for .get() +- add lu_ent_has(), and a python has_key() method to Entity types +- don't include tools in the binary package +- add translated strings + +* Thu Jul 19 2001 Nalin Dahyabhai +- lib/user.c: catch and ignore errors when running stacks +- lusermod: fix slightly bogus help messages +- luseradd: when adding a user and group, use the gid of the group + instead of the user's uid as the primary group +- properly set the password field in user accounts created using + auth-only auth modules (shadow needs "x" instead of "!!") +- implement home directory removal, start on population + +* Wed Jul 18 2001 Nalin Dahyabhai +- fix group password setting in the files module +- setpass affects both auth and info, so run both stacks + +* Tue Jul 17 2001 Nalin Dahyabhai +- make the testbed apps noinst + +* Mon Jul 16 2001 Nalin Dahyabhai +- fix errors due to uninitialized fields in the python bindings +- add kwargs support to all python wrappers +- add a mechanism for passing arguments to python callbacks + +* Wed Jul 11 2001 Nalin Dahyabhai +- stub out the krb5 and ldap modules so that they'll at least compile again + +* Tue Jul 10 2001 Nalin Dahyabhai +- don't bail when writing empty fields to colon-delimited files +- use permissions of the original file when making backup files instead of 0600 + +* Fri Jul 6 2001 Nalin Dahyabhai +- finish implementing is_locked methods in files/shadow module +- finish cleanup of the python bindings +- allow conditional builds of modules so that we can build without + all of the prereqs for all of the modules + +* Thu Jun 21 2001 Nalin Dahyabhai +- add error reporting facilities +- split public header into pieces by function +- backend cleanups + +* Mon Jun 18 2001 Nalin Dahyabhai +- make %%{name}-devel require %%{name} and not %%{name}-devel + +* Fri Jun 15 2001 Nalin Dahyabhai +- clean up quota bindings some more +- finish most of the ldap bindings +- fix a subtle bug in the files module that would show up when renaming accounts +- fix mapping methods for entity structures in python + +* Thu Jun 14 2001 Nalin Dahyabhai +- get bindings for prompts to work correctly +- clean up some of the add/remove semantics (set source on add) +- ldap: implement enumeration +- samples/enum: fix the argument order + +* Wed Jun 13 2001 Nalin Dahyabhai +- clean up python bindings for quota + +* Tue Jun 12 2001 Nalin Dahyabhai 0.11 +- finish up python bindings for quota support + +* Sun Jun 10 2001 Nalin Dahyabhai +- finish up quota support libs + +* Fri Jun 8 2001 Nalin Dahyabhai +- start quota support library to get some type safety + +* Thu Jun 7 2001 Nalin Dahyabhai +- start looking at quota manipulation + +* Wed Jun 6 2001 Nalin Dahyabhai +- add functions for enumerating users and groups, optionally per-module +- lusermod.c: -s should specify the shell, not the home directory + +* Fri Jun 1 2001 Nalin Dahyabhai 0.10 +- finish the python bindings and verify that the file backend works again + +* Wed May 30 2001 Nalin Dahyabhai +- remove a redundant check which was breaking modifications + +* Tue May 29 2001 Nalin Dahyabhai +- finish adding setpass methods + +* Wed May 2 2001 Nalin Dahyabhai 0.9 +- get a start on some Python bindings + +* Tue May 1 2001 Nalin Dahyabhai 0.8.2 +- make binary-incompatible change in headers + +* Mon Apr 30 2001 Nalin Dahyabhai 0.8.1 +- add doxygen docs and a "doc" target for them + +* Sat Jan 20 2001 Nalin Dahyabhai 0.8 +- add a "quiet" prompter +- add --interactive flag to sample apps and default to using quiet prompter +- ldap: attempt a "self" bind if other attempts fail +- krb5: connect to the password-changing service if the user principal has + the NULL instance + +* Wed Jan 10 2001 Nalin Dahyabhai +- the great adding-of-the-copyright-statements +- take more care when creating backup files in the files module + +* Wed Jan 3 2001 Nalin Dahyabhai 0.7 +- add openldap-devel as a buildprereq +- krb5: use a continuous connection +- krb5: add "realm" config directive +- ldap: use a continuous connection +- ldap: add "server", "basedn", "binddn", "user", "authuser" config directives +- ldap: actually finish the account deletion function +- ldap: don't send cleartext passwords to the directory +- fix naming attribute for users (should be uid, not gid) +- refine the search-by-id,convert-to-name,search-by-name logic +- fix handling of defaults when the config file is read in but contains no value +- implement an LDAP information store +- try to clean up module naming with libtool +- luseradd: pass plaintext passwords along +- luseradd: use symbolic attribute names instead of hard-coded +- lusermod: pass plaintext passwords along +- lgroupadd: pass plaintext passwords along +- lgroupmod: pass plaintext passwords along +- add libuser as a dependency of libuser-devel + +* Tue Jan 2 2001 Nalin Dahyabhai 0.6 +- initial packaging