SUDO_LOGSRV.PROTO(5) File Formats Manual SUDO_LOGSRV.PROTO(5)

sudo_logsrv.proto — پروتکل سرویس لاگ رخدادها و نشستهای sudo

از نسخهٔ 1.9.0 به بعد، sudo از ارسال لاگ‌های رخداد و ورودی/خروجی (I/O) به یک سرور لاگ پشتیبانی می‌کند. پروتکل مورد استفاده در زبان ویژه‌دامنهٔ Protocol Buffers گوگل نوشته شده است. بخش مثال‌ها (EXAMPLES) شامل توصیف کاملی از این پروتکل در قالب Protocol Buffers است.

از آنجا که هنگام استفاده از Protocol Buffers راهی برای تعیین مرز پیام‌ها وجود ندارد، اندازه ارسالی هر پیام روی شبکه، بلافاصله پیش از خود پیام به صورت یک عدد صحیح ۳۲ بیتی بدون علامت در ترتیب بایتی شبکه (network byte order) فرستاده می‌شود. به این روش “length-prefix framing” (قاب‌بندی با پیشوند طول) گفته می‌شود و همان شیوه‌ای است که گوگل برای مدیریت نبود جداکننده‌های پیام پیشنهاد می‌کند.

این پروتکل از دو پیام اصلی تشکیل شده است: ClientMessage و ServerMessage که در زیر شرح داده شده‌اند. سرور باید پیام‌هایی تا اندازهٔ دو مگابایت را بپذیرد. در صورتی که کلاینت پیامی بزرگ‌تر از دو مگابایت ارسال کند، سرور ممکن است یک خطا برگرداند.

یک ClientMessage ظرفی است که برای کپسوله‌سازی تمام انواع پیام‌های ممکنی که یک کلاینت ممکن است به سرور ارسال کند، به کار می‌رود.

message ClientMessage {
  oneof type {
    AcceptMessage accept_msg = 1;
    RejectMessage reject_msg = 2;
    ExitMessage exit_msg = 3;
    RestartMessage restart_msg = 4;
    AlertMessage alert_msg = 5;
    IoBuffer ttyin_buf = 6;
    IoBuffer ttyout_buf = 7;
    IoBuffer stdin_buf = 8;
    IoBuffer stdout_buf = 9;
    IoBuffer stderr_buf = 10;
    ChangeWindowSize winsize_event = 11;
    CommandSuspend suspend_event = 12;
    ClientHello hello_msg = 13;
  }
}

زیرپیام‌های مختلف ClientMessage که کلاینت ممکن است به سرور ارسال کند در ادامه شرح داده شده‌اند.

message TimeSpec {
    int64 tv_sec = 1;
    int32 tv_nsec = 2;
}

یک TimeSpec معادل ساختار struct timespec در POSIX است که شامل اعضای ثانیه و نانوثانیه می‌باشد. عضو یک عدد صحیح ۶۴ بیتی است تا از تاریخ‌های پس از سال ۲۰۳۸ پشتیبانی کند.

message InfoMessage {
  message StringList {
    repeated string strings = 1;
  }
  message NumberList {
    repeated int64 numbers = 1;
  }
  string key = 1;
  oneof value {
    int64 numval = 2;
    string strval = 3;
    StringList strlistval = 4;
    NumberList numlistval = 5;
  }
}

یک InfoMessage برای نشان دادن اطلاعات دربارهٔ کاربر فراخواننده و همچنین محیط اجرایی که دستور در آن اجرا می‌شود به صورت جفت‌های کلید-مقدار استفاده می‌شود. کلید همیشه یک رشته است، اما مقدار ممکن است یک عدد صحیح ۶۴ بیتی، یک رشته، آرایه‌ای از رشته‌ها، یا آرایه‌ای از اعداد صحیح ۶۴ بیتی باشد. داده‌های لاگ رخداد از مدخل‌های InfoMessage تشکیل شده‌اند. برای اطلاعات بیشتر بخش متغیرهای لاگ رخداد (EVENT LOG VARIABLES) را ببینید.

message ClientHello {
  string client_id = 1;
}

یک پیام ClientHello شامل اطلاعات کلاینت است که ممکن است هنگام اولین اتصال کلاینت به سرور فرستاده شود.

client_id
توصیفی با ساختار آزاد از کلاینت. این مقدار معمولاً شامل نام و نسخهٔ پیاده‌سازی کلاینت است.

message AcceptMessage {
  TimeSpec submit_time = 1;
  repeated InfoMessage info_msgs = 2;
  bool expect_iobufs = 3;
}

یک AcceptMessage هنگامی توسط کلاینت ارسال می‌شود که یک دستور توسط خط‌مشی امنیتی مجاز دانسته شود. این پیام شامل اعضای زیر است:

submit_time
زمان ساعت دیواری هنگام ارسال دستور به خط‌مشی امنیتی.
info_msgs
آرایه‌ای از InfoMessage توصیف‌کنندهٔ کاربری که دستور را ارسال کرده و همچنین محیط اجرای دستور. این اطلاعات برای تولید یک مدخل لاگ رخداد استفاده می‌شود و ممکن است توسط سرور نیز برای تعیین مکان و چگونگی ذخیره‌سازی لاگ I/O به کار رود.
expect_iobufs
اگر سرور باید در ادامه منتظر پیام‌های IoBuffer باشد (برای لاگ‌گیری I/O) روی true تنظیم می‌شود، یا اگر سرور تنها باید لاگ رخداد را ذخیره کند روی false قرار می‌گیرد.

در صورت ارسال یک AcceptMessage ، کلاینت نباید یک RejectMessage یا RestartMessage ارسال کند.

message RejectMessage {
  TimeSpec submit_time = 1;
  string reason = 2;
  repeated InfoMessage info_msgs = 3;
}

یک RejectMessage هنگامی توسط کلاینت ارسال می‌شود که یک دستور توسط خط‌مشی امنیتی رد شود. این پیام شامل اعضای زیر است:

submit_time
زمان ساعت دیواری هنگامی که دستور به خط‌مشی امنیتی ارائه شد.
reason
دلیلی که خط‌مشی امنیتی برای رد کردن دستور ارائه داده است.
info_msgs
آرایه‌ای از InfoMessage توصیف‌کنندهٔ کاربری که دستور را ارسال کرده و همچنین محیط اجرای دستور. این اطلاعات برای تولید یک مدخل لاگ رخداد استفاده می‌شود.

در صورت ارسال یک RejectMessage ، کلاینت نباید یک AcceptMessage یا RestartMessage ارسال کند.

message ExitMessage {
  TimeSpec run_time = 1;
  int32 exit_value = 2;
  bool dumped_core = 3;
  string signal = 4;
  string error = 5;
}

یک ExitMessage توسط کلاینت پس از خروج دستور یا خاتمه یافتن آن توسط یک سیگنال ارسال می‌شود. این پیام شامل اعضای زیر است:

run_time
کل مدت‌زمان سپری‌شده از زمان آغاز دستور، که در صورت امکان با استفاده از یک ساعت یکنواخت (monotonic clock) محاسبه می‌شود. این مقدار زمان ساعت دیواری نیست.
exit_value
مقدار خروج دستور در بازهٔ ۰ تا ۲۵۵.
dumped_core
در صورتی که دستور توسط یک سیگنال خاتمه یافته و core dump تولید کرده باشد، برابر با true خواهد بود.
signal
اگر دستور توسط یک سیگنال پایان یافته باشد، این مقدار روی نام سیگنال بدون پیشوند “SIG” تنظیم می‌شود. برای نمونه: INT, TERM, KILL, SEGV.
error
پیامی از کلاینت که نشان می‌دهد دستور به دلیل یک خطا به طور غیرمنتظره خاتمه یافته است.

هنگام انجام لاگ‌گیری I/O، کلاینت باید پیش از بستن اتصال منتظر یک commit_point متناظر با آخرین IoBuffer بماند، مگر آنکه آخرین commit_point قبلاً دریافت شده باشد.

message RestartMessage {
  string log_id = 1;
  TimeSpec resume_point = 2;
}

یک RestartMessage توسط کلاینت برای ازسرگیری ارسال یک لاگ I/O موجود که قبلاً متوقف شده بود ارسال می‌شود. این پیام شامل اعضای زیر است:

log_id
نام سمت سرور برای یک لاگ I/O که قبلاً توسط سرور به کلاینت فرستاده شده بود. این مقدار ممکن است یک مسیر در سرور یا نوع دیگری از شناسهٔ سمت سرور باشد.
resume_point
نقطهٔ زمانی که لاگ I/O باید پس از آن از سر گرفته شود. این مقدار در قالب یک TimeSpec است که بیانگر مدت‌زمان سپری‌شده از زمان آغاز دستور است، نه زمان ساعت دیواری. مقدار resume_point باید با یک commit_point که قبلاً توسط سرور به کلاینت فرستاده شده بود همخوانی داشته باشد. اگر سرور یک RestartMessage دریافت کند که شامل یک resume_point باشد که پیش‌تر ندیده است، خطایی به کلاینت بازگردانده شده و اتصال قطع می‌شود.

در صورت ارسال یک RestartMessage ، کلاینت نباید یک AcceptMessage یا RejectMessage ارسال کند.

message AlertMessage {
  TimeSpec alert_time = 1;
  string reason = 2;
  repeated InfoMessage info_msgs = 3;
}

یک AlertMessage توسط کلاینت فرستاده می‌شود تا مشکلی را که در حین اجرای دستور توسط خط‌مشی امنیتی شناسایی شده و باید در لاگ رخداد ذخیره شود نشان دهد. این پیام شامل اعضای زیر است:

alert_time
زمان ساعت دیواری هنگام رخ دادن هشدار.
reason
دلیل هشدار.
info_msgs
آرایه‌ای اختیاری از InfoMessage توصیف‌کنندهٔ کاربری که دستور را ارائه کرده و همچنین محیط اجرای دستور. این اطلاعات برای تولید یک مدخل لاگ رخداد استفاده می‌شود.

message IoBuffer {
  TimeSpec delay = 1;
  bytes data = 2;
}

یک IoBuffer برای نمایش داده‌های ورودی ترمینال، خروجی ترمینال، ورودی استاندارد، خروجی استاندارد، یا خطای استاندارد استفاده می‌شود. این پیام شامل اعضای زیر است:

delay
زمان سپری‌شده از آخرین رکورد در قالب یک TimeSpec. مقدار delay در صورت امکان باید با استفاده از یک ساعت یکنواخت محاسبه شود.
data
داده‌های باینری لاگ I/O از ورودی ترمینال، خروجی ترمینال، ورودی استاندارد، خروجی استاندارد، یا خطای استاندارد.

message ChangeWindowSize {
  TimeSpec delay = 1;
  int32 rows = 2;
  int32 cols = 3;
}

یک پیام هنگامی توسط کلاینت ارسال می‌شود که اندازهٔ ترمینال اجراکنندهٔ دستور تغییر کند. این پیام شامل اعضای زیر است:

delay
زمان سپری‌شده از آخرین رکورد در قالب یک TimeSpec. مقدار delay در صورت امکان باید با استفاده از یک ساعت یکنواخت محاسبه شود.
rows
تعداد سطرهای جدید ترمینال.
cols
تعداد ستون‌های جدید ترمینال.

message CommandSuspend {
  TimeSpec delay = 1;
  string signal = 2;
}

یک پیام توسط کلاینت هنگامی ارسال می‌شود که دستور معلق یا ازسرگرفته شود. این پیام شامل اعضای زیر است:

delay
زمان سپری‌شده از آخرین رکورد در قالب یک TimeSpec. مقدار delay در صورت امکان باید با استفاده از یک ساعت یکنواخت محاسبه شود.
signal
نام سیگنال بدون پیشوند “SIG”. برای نمونه: STOP, TSTP, CONT.

یک ServerMessage ظرفی است که برای کپسوله‌سازی تمام انواع پیام‌های ممکنی که سرور ممکن است به یک کلاینت بفرستد استفاده می‌شود.

message ServerMessage {
  oneof type {
    ServerHello hello = 1;
    TimeSpec commit_point = 2;
    string log_id = 3;
    string error = 4;
    string abort = 5;
  }
}

زیرپیام‌های مختلف ServerMessage که سرور ممکن است به کلاینت ارسال کند در ادامه شرح داده شده‌اند.

message ServerHello {
  string server_id = 1;
  string redirect = 2;
  repeated string servers = 3;
  bool subcommands = 4;
}

پیام ServerHello شامل اطلاعات سرور است که هنگام اولین اتصال کلاینت ارسال می‌شود. این پیام شامل اعضای زیر است:

server_id
توصیفی با فرمت آزاد از سرور. معمولاً شامل نام و نسخهٔ پیاده‌سازی اجراشده روی سرور لاگ است. این عضو همیشه وجود دارد.
redirect
یک میزبان و پورت که با دو نقطه (‘’): از هم جدا شده‌اند و کلاینت باید به جای آن به این آدرس متصل شود. میزبان می‌تواند یک نام میزبان، یک آدرس IPv4، یا یک آدرس IPv6 در داخل براکت‌ها باشد. این ویژگی ممکن است برای توازن بار سرور (load balancing) استفاده شود. سرور پس از ارسال ServerHello در صورتی که شامل یک باشد ارتباط را قطع خواهد کرد.
servers
فهرستی از دیگر سرورهای لاگ شناخته‌شده. این مورد می‌تواند برای پیاده‌سازی افزونگی (redundancy) سرور لاگ استفاده شود و به کلاینت امکان می‌دهد تمامی سرورهای لاگ دیگر را صرفاً با اتصال به یک سرور شناخته‌شده کشف کند. در صورتی که فقط یک سرور لاگ وجود داشته باشد، این عضو ممکن است حذف شود.
subcommands
اگر تنظیم شده باشد، سرور از لاگ‌گیری دستورات اضافی در طول یک نشست پشتیبانی می‌کند. کلاینت ممکن است هنگامی که sudo در حالت (رهگیری) در حال اجرا است یک AcceptMessage یا RejectMessage ارسال کند. در این حالت، دستوراتی که از دل دستور اولیه‌ای که توسط sudo مجاز شده بود ایجاد می‌شوند نیز مشمول محدودیت‌های خط‌مشی بوده و/یا ثبت می‌شوند. اگر برابر با false باشد، کلاینت نباید برای ثبت لاگ دستورات اضافی تلاش کند.

یک برچسب زمانی دوره‌ای ارسال‌شده توسط سرور است که نشان می‌دهد بافرهای لاگ I/O در چه زمانی در فضای ذخیره‌سازی ثبت نهایی (commit) شده‌اند. این پیام پس از هر IoBuffer ارسال نمی‌شود بلکه در بازه‌های زمانی قابل‌پیکربندی روی سرور ارسال می‌گردد. هنگامی که سرور یک ExitMessage دریافت می‌کند، پیش از بستن اتصال با یک commit_point متناظر با آخرین IoBuffer دریافت‌شده پاسخ خواهد داد.

شناسهٔ سمت سرور برای لاگ I/O در حال ذخیره‌سازی که در پاسخ به یک AcceptMessage که در آن expect_iobufs برابر با true است ارسال می‌شود.

یک خطای مهلک سمت سرور. سرور پس از ارسال پیام error اتصال را خواهد بست.

یک پیام abort از سوی سرور نشان می‌دهد کلاینت باید دستور را خاتمه داده (kill) و نشست را پایان دهد. این پیام ممکن است برای اعمال خط‌مشی ساده در سمت سرور استفاده شود. سرور پس از ارسال پیام abort اتصال را خواهد بست.

جریان مورد انتظار پروتکل به شرح زیر است:

  1. کلاینت به نخستین سرور در دسترس متصل می‌شود. اگر کلاینت برای استفاده از TLS پیکربندی شده باشد، یک دست‌تکانی (handshake) TLS انجام خواهد گرفت.
  2. کلاینت پیام ClientHello را ارسال می‌کند. این پیام در حال حاضر اختیاری است اما به سرور امکان می‌دهد اتصال غیر TLS را روی پورت TLS تشخیص دهد.
  3. سرور پیام ServerHello را ارسال می‌کند.
  4. کلاینت با یکی از پیام‌های AcceptMessage ، RejectMessage یا RestartMessage پاسخ می‌دهد.
  5. اگر کلاینت یک AcceptMessage همراه با تنظیم بودن expect_iobufs ارسال کرده باشد، سرور یک لاگ I/O جدید ایجاد کرده و با یک پاسخ می‌دهد.
  6. کلاینت صفر یا چند پیام IoBuffer ارسال می‌کند.
  7. سرور به طور دوره‌ای به پیام‌های IoBuffer با یک commit_point پاسخ می‌دهد.
  8. کلاینت هنگام خروج یا کشته شدن دستور یک ExitMessage ارسال می‌کند.
  9. اگر یک commit_point معلق مانده باشد، سرور آخرین commit_point را ارسال می‌کند.
  10. سرور اتصال را می‌بندد. پس از دریافت آخرین commit_point ، اگر TLS در حال استفاده باشد کلاینت سمت خود از اتصال TLS را خاموش کرده و اتصال را می‌بندد.
  11. سرور در صورت استفاده از TLS سمت خود از اتصال TLS را خاموش کرده و اتصال را می‌بندد.

در هر لحظه، سرور ممکن است یک پیام error یا abort به کلاینت ارسال کند که در این صورت سرور اتصال را خواهد بست. اگر یک پیام abort دریافت شود، کلاینت باید اجرای دستور جاری را متوقف کند.

کلاس‌های AcceptMessage ، AlertMessage و RejectMessage شامل آرایه‌ای از InfoMessage هستند که باید حاوی اطلاعاتی دربارهٔ کاربری که دستور را ارسال کرده و همچنین اطلاعات مربوط به محیط اجرای دستور در صورت پذیرفته شدن آن باشند.

برخی متغیرها دارای پیشوند client ، run یا submit هستند. این پیشوندها برای رفع ابهام برای متغیرهایی به کار می‌روند که ممکن است برای برنامهٔ کلاینت، کاربر ارسال‌کنندهٔ دستور، یا دستوری که اجرا می‌شود صدق کنند. متغیرهایی با پیشوند client مربوط به برنامه‌ای هستند که اتصال را با سرور لاگ برقرار می‌کند، برای نمونه sudo. متغیرهایی با پیشوند run مربوط به دستوری هستند که کاربر درخواست اجرای آن را داشته است. متغیرهایی با پیشوند submit مربوط به کاربری هستند که درخواست را ارسال کرده است (کاربری که sudo را اجرا می‌کند).

مدخل‌های InfoMessage زیر الزامی هستند:

کلید نوع توضیحات
command string دستوری که ارسال شد
runuser string نام کاربری که دستور با هویت او اجرا شد
submithost string نام میزبانی که دستور روی آن ارسال شد
submituser string نام کاربری که دستور را ارسال کرد

مدخل‌های InfoMessage زیر شناخته‌شده هستند، اما الزامی نیستند:

کلید نوع توضیحات
clientargv StringList بردار آرگومان اصلی کلاینت
clientpid int64 شناسه پردازه (PID) کلاینت
clientppid int64 شناسه پردازه والد (PPID) کلاینت
clientsid int64 شناسه نشست ترمینال کلاینت
columns int64 تعداد ستون‌های ترمینال
lines int64 تعداد خطوط ترمینال
runargv StringList بردار آرگومان دستوری که اجرا می‌شود
runchroot string دایرکتوری ریشه دستوری که اجرا می‌شود
runcwd string دایرکتوری کاری دستوری که در حال اجرا است
runenv StringList متغیرهای محیطی دستور در حال اجرا
rungid int64 شناسه گروه اصلی (GID) دستور
rungids NumberList شناسه‌های گروه تکمیلی برای دستور
rungroup string نام گروه اصلی دستور
rungroups StringList نام‌های گروه‌های تکمیلی برای دستور
runuid int64 شناسه کاربری (UID) دستوری که اجرا می‌شود
submitcwd string دایرکتوری کاری جاری کاربر ارسال‌کننده
submitenv StringList متغیرهای محیطی کاربر ارسال‌کننده
submitgid int64 شناسه گروه اصلی (GID) کاربر ارسال‌کننده
submitgids NumberList شناسه‌های گروه تکمیلی کاربر ارسال‌کننده
submitgroup string نام گروه اصلی کاربر ارسال‌کننده
submitgroups StringList نام گروه‌های تکمیلی کاربر ارسال‌کننده
submituid int64 شناسه کاربری (UID) کاربر ارسال‌کننده
ttyname string ترمینالی که دستور از آن ارسال شده است

سرور باید متغیرهای دیگری را که در بالا فهرست نشده‌اند بپذیرد، اما می‌تواند آن‌ها را نادیده بگیرد.

توصیف پروتکل سرور لاگ در Protocol Buffers با استفاده از نحو “proto3” به طور کامل در ادامه آورده شده است.

syntax = "proto3";

/*
 * Client message to the server.  Messages on the wire are
 * prefixed with a 32-bit size in network byte order.
 */
message ClientMessage {
  oneof type {
    AcceptMessage accept_msg = 1;
    RejectMessage reject_msg = 2;
    ExitMessage exit_msg = 3;
    RestartMessage restart_msg = 4;
    AlertMessage alert_msg = 5;
    IoBuffer ttyin_buf = 6;
    IoBuffer ttyout_buf = 7;
    IoBuffer stdin_buf = 8;
    IoBuffer stdout_buf = 9;
    IoBuffer stderr_buf = 10;
    ChangeWindowSize winsize_event = 11;
    CommandSuspend suspend_event = 12;
  }
}

/* Equivalent of POSIX struct timespec */
message TimeSpec {
    int64 tv_sec = 1;		/* seconds */
    int32 tv_nsec = 2;		/* nanoseconds */
}

/* I/O buffer with keystroke data */
message IoBuffer {
  TimeSpec delay = 1;		/* elapsed time since last record */
  bytes data = 2;		/* keystroke data */
}

/*
 * Key/value pairs, like Privilege Manager struct info.
 * The value may be a number, a string, or a list of strings.
 */
message InfoMessage {
  message StringList {
    repeated string strings = 1;
  }
  message NumberList {
    repeated int64 numbers = 1;
  }
  string key = 1;
  oneof value {
    int64 numval = 2;
    string strval = 3;
    StringList strlistval = 4;
    NumberList numlistval = 5;
  }
}

/*
 * Event log data for command accepted by the policy.
 */
message AcceptMessage {
  TimeSpec submit_time = 1;		/* when command was submitted */
  repeated InfoMessage info_msgs = 2;	/* key,value event log data */
  bool expect_iobufs = 3;		/* true if I/O logging enabled */
}

/*
 * Event log data for command rejected by the policy.
 */
message RejectMessage {
  TimeSpec submit_time = 1;		/* when command was submitted */
  string reason = 2;			/* reason command was rejected */
  repeated InfoMessage info_msgs = 3;	/* key,value event log data */
}

/* Message sent by client when command exits. */
/* Might revisit runtime and use end_time instead */
message ExitMessage {
  TimeSpec run_time = 1;	/* total elapsed run time */
  int32 exit_value = 2;		/* 0–255 */
  bool dumped_core = 3;		/* true if command dumped core */
  string signal = 4;		/* signal name if killed by signal */
  string error = 5;		/* if killed due to other error */
}

/* Alert message, policy module-specific. */
message AlertMessage {
  TimeSpec alert_time = 1;		/* time alert message occurred */
  string reason = 2;			/* policy alert error string */
  repeated InfoMessage info_msgs = 3;	/* key,value event log data */
}

/* Used to restart an existing I/O log on the server. */
message RestartMessage {
  string log_id = 1;		/* ID of log being restarted */
  TimeSpec resume_point = 2;	/* resume point (elapsed time) */
}

/* Window size change event. */
message ChangeWindowSize {
  TimeSpec delay = 1;		/* elapsed time since last record */
  int32 rows = 2;		/* new number of rows */
  int32 cols = 3;		/* new number of columns */
}

/* Command suspend/resume event. */
message CommandSuspend {
  TimeSpec delay = 1;		/* elapsed time since last record */
  string signal = 2;		/* signal that caused suspend/resume */
}

/*
 * Server messages to the client.  Messages on the wire are
 * prefixed with a 32-bit size in network byte order.
 */
message ServerMessage {
  oneof type {
    ServerHello hello = 1;	/* server hello message */
    TimeSpec commit_point = 2;	/* cumulative time of records stored */
    string log_id = 3;		/* ID of server-side I/O log */
    string error = 4;		/* error message from server */
    string abort = 5;		/* abort message, kill command */
  }
}

/* Hello message from server when client connects. */
message ServerHello {
  string server_id = 1;		/* free-form server description */
  string redirect = 2;		/* optional redirect if busy */
  repeated string servers = 3;	/* optional list of known servers */
}

sudo_logsrvd.conf(5), sudoers(5), sudo(8), sudo_logsrvd(8) Protocol Buffers, https://protobuf.dev.

افراد زیادی در طول سال‌ها روی sudo کار کرده‌اند؛ این نسخه شامل کدهایی است که عمدتاً توسط افراد زیر نوشته شده است:

Todd C. Miller

برای فهرست کاملی از افرادی که در sudo مشارکت داشته‌اند، پروندهٔ CONTRIBUTORS.md را در توزیع sudo (https://www.sudo.ws/about/contributors) ببینید.

اگر فکر می‌کنید باگی در sudo_logsrv.proto یافته‌اید، می‌توانید یک گزارش باگ در پایگاه‌داده باگ‌های sudo در https://bugzilla.sudo.ws ثبت کنید، یا یک issue در https://github.com/sudo-project/sudo/issues باز کنید. اگر ترجیح می‌دهید از رایانامه استفاده کنید، پیام‌ها می‌توانند به فهرست پستی sudo-workers در https://www.sudo.ws/mailman/listinfo/sudo-workers (عمومی) یا به <sudo@sudo.ws> (خصوصی) ارسال شوند.

لطفاً آسیب‌پذیری‌های امنیتی را از طریق issueهای عمومی گیت‌هاب، باگزیلا یا فهرست‌های پستی گزارش ندهید. در عوض، آن‌ها را از طریق رایانامه به <Todd.Miller@sudo.ws> گزارش کنید. در صورت تمایل می‌توانید پیام خود را با استفاده از کلید موجود در https://www.sudo.ws/dist/PGPKEYS توسط PGP رمزنگاری کنید.

پشتیبانی محدود رایگان از طریق فهرست پستی sudo-users در دسترس است؛ برای عضویت یا جستجو در بایگانی‌ها به https://www.sudo.ws/mailman/listinfo/sudo-users مراجعه کنید.

sudo به صورت “همان‌طور که هست” (AS IS) ارائه می‌شود و هرگونه ضمانت صریح یا ضمنی، از جمله، اما نه محدود به، ضمانت‌های ضمنی قابلیت فروش و تناسب برای یک هدف خاص سلب می‌گردد. برای جزئیات کامل، پروندهٔ LICENSE.md توزیع‌شده با sudo یا https://www.sudo.ws/about/license را ببینید.

September 13, 2022 Sudo 1.9.17p2