ตรวจสอบหมายเลขอ้างอิงของพอยน์เตอร์ว่าถูกต้อง

ฉันต้องการใช้ไลบรารี Microsoft CryptographicServiceProvider และขณะนี้ฉันกำลังคิดถึงวิธีที่ดีที่สุดในการจัดการกับตัวจัดการบริบทที่ฉันสร้างขึ้น

คำถามของฉันเฉพาะเจาะจงสำหรับกรณีนี้ แต่แนวทางการออกแบบสามารถใช้ในสถานการณ์อื่นได้

ฉันมาจากพื้นหลังของโค้ดที่ได้รับการจัดการ และฉันไม่มั่นใจ 100% เกี่ยวกับการจัดการตัวชี้แบบมัลติเธรดใน C/C++

โดยทั่วไปมีสองฟังก์ชันที่รับผิดชอบในการสร้างและทำลายหมายเลขอ้างอิง (CryptAcquireContext, CryptReleaseContext) และฟังก์ชัน CSP ที่ตามมาทั้งหมดจะใช้หมายเลขอ้างอิงซึ่งส่งคืนโดยฟังก์ชันผู้สร้าง

ฉันไม่พบข้อมูลที่เป็นรูปธรรมหรือข้อกำหนดเฉพาะจาก Microsoft ที่ให้แนวทางการออกแบบหรือกฎเกณฑ์ว่าต้องทำอย่างไร แต่ฉันได้ค้นคว้ากับผู้ให้บริการ CSP รายอื่นที่สร้างโดย Microsoft เพื่อค้นหากฎการออกแบบ ซึ่งได้แก่:

  • ฟังก์ชันจะต้องปลอดภัยสำหรับเธรด
  • หมายเลขอ้างอิงบริบทจะไม่ถูกใช้ร่วมกันระหว่างเธรด
  • หากตัวจัดการบริบทไม่ถูกต้องส่งคืนพร้อมข้อผิดพลาด

ผู้ให้บริการ MS CSP รายอื่นจะส่งคืนตัวชี้ที่ถูกต้องเป็นตัวจัดการ หรือหากไม่เป็นเช่นนั้น จะเป็นโมฆะ

ฉันไม่คิดว่าแอปพลิเคชันที่เรียกจะผ่านขยะทั้งหมด แต่อาจเกิดขึ้นได้ว่ามันผ่านตัวจัดการที่เผยแพร่แล้วและไลบรารีของฉันควรกลับมาพร้อมข้อผิดพลาด

สิ่งนี้ทำให้ฉันมีแนวคิดสามประการในการนำไปปฏิบัติ:

  1. เพียงจัดสรรหน่วยความจำของโครงสร้างบริบทของฉันด้วย malloc หรือใหม่แล้วส่งคืนตัวชี้ดิบเป็นที่จับ

    ฉันคาดหวังได้ว่าแอปพลิเคชันที่เรียกใช้ไลบรารีของฉันจะผ่านการจัดการที่ถูกต้อง แต่ถ้าไม่ใช่ห้องสมุดของฉันก็จะพบกับพฤติกรรมที่ไม่ได้กำหนดไว้ ดังนั้นฉันจึงต้องการทางออกที่ดีกว่า

  2. เพิ่มตัวชี้ที่ฉันสร้างลงในรายการ (std::list, std::map) ดังนั้นฉันจึงสามารถวนซ้ำรายการเพื่อตรวจสอบว่ามีตัวชี้อยู่หรือไม่ การเข้าถึงรายการได้รับการปกป้องด้วย mutex

    สิ่งนี้ควรปลอดภัยและการใช้ API ตามปกติไม่ควรเป็นปัญหาด้านประสิทธิภาพ แต่ในสถานการณ์ Terminal Server ก็อาจเป็นได้ ในกรณีนี้ กระบวนการ Windows lsass.exe สร้างขึ้นสำหรับผู้ใช้ทุกคนที่ต้องการเข้าสู่ระบบบริบท CSP ในเธรดที่แยกจากกัน และทำการเรียก API ประมาณ 10 ครั้งต่อบริบท

    เป้าหมายการออกแบบคือห้องสมุดของฉันควรจะสามารถรองรับไคลเอนต์ 300 รายพร้อมกันได้ ฉันไม่รู้ว่า Windows สร้างขึ้นกี่เธรดในกรณีนี้

    ดังนั้นถ้าเป็นไปได้ ฉันอยากจะใช้งานแบบไม่มีล็อคมากกว่า

  3. ฉันจัดสรรโครงสร้างพื้นฐานที่เก็บค่าตรวจสอบและตัวชี้ของข้อมูลจริง ใช้ตัวชี้ของโครงสร้างนี้เป็นตัวจัดการบริบท

    typedef struct CSPHandle  
    {  
        int Type; // (eg. magic number CSPContext=0xA1B2C3D4)  
        CSPContextPtr pCSPContext;  
    };
    

    ดังนั้นฉันจึงสามารถอ่านไบต์แรกของตัวชี้ที่ส่งผ่านและตรวจสอบว่าข้อมูลตรงกับประเภทที่ฉันกำหนดหรือไม่ และฉันมีการควบคุมอย่างเต็มที่เกี่ยวกับตัวชี้ข้อมูลจริง ซึ่งตั้งค่าเป็น NULL หากบริบทถูกเผยแพร่ นี่เป็นความคิดที่ดีหรือไม่ดี?

คุณคิดอย่างไรเกี่ยวกับคดีนี้? ฉันควรใช้วิธีใดวิธีหนึ่งเหล่านี้หรือมีวิธีแก้ไขปัญหาอื่นหรือไม่

ขอบคุณ


person Stephan Weitlaner    schedule 04.03.2015    source แหล่งที่มา
comment
I can expect that the applications which call my library will pass a valid handle. But if not my library will run into an undefined behaviour. สมมติว่าคุณอาจค้นพบว่าหมายเลขอ้างอิงที่ส่งผ่านนั้นไม่ถูกต้อง รหัสของคุณจะทำอะไร? นอกจากนี้ คุณควรชั่งน้ำหนักข้อดีและข้อเสียของการพยายามจับมือมากเกินไป หากผู้ใช้ API ของคุณเป็นโปรแกรมเมอร์ที่มีประสบการณ์ บางทีแค่บันทึกว่าพวกเขาจำเป็นต้องผ่านการจัดการที่ถูกต้อง ไม่เช่นนั้นสิ่งเลวร้ายอาจเกิดขึ้นก็อาจเพียงพอแล้ว   -  person PaulMcKenzie    schedule 04.03.2015


คำตอบ (1)


ฉันพบวิธีแก้ปัญหาแล้วและจะตอบคำถามของฉัน

ฉันมองข้ามรายละเอียดเล็กๆ น้อยๆ แต่สำคัญไป

ใน CSP ไม่มีการเรียก API โดยตรงไปยัง dll (โหลดไลบรารี รับตัวชี้ฟังก์ชัน ฟังก์ชันการโทร) เนื่องจากการเรียกฟังก์ชันจะถูกส่งต่อโดย Microsoft CSP ซึ่งจะโหลดไลบรารี CSP ตามชื่อ

ดังนั้น Microsoft CSP จำเป็นต้องทราบและตรวจสอบบริบทที่ส่งผ่านเพื่อให้ได้การแมปที่ถูกต้องไปยังไลบรารีเฉพาะ

ตัวอย่าง:
1. client->cryptacquirecontext(in cspname, out ctx)
2. MS CSP->โหลด libray จาก cspname
3 . MS CSP->เรียกตัวชี้ฟังก์ชันของไลบรารีที่โหลด
4. CSP LIB->cryptacquirecontext สร้างบริบทใหม่
5. MS CSP->รับหมายเลขอ้างอิง csp ที่ส่งคืนและบันทึกลงในการแมป dll
6. MS CSP->ส่งคืนผลลัพธ์ไปยังแอปพลิเคชันที่เรียกใช้
7. client->cryptsetprovparam(ctx) // ซึ่งถูกสร้างขึ้นก่อน
8. MS CSP->ตรวจสอบว่ามีบริบทอยู่หรือไม่และไลบรารีใดที่รับผิดชอบ
9. MS CSP->ถ้าบริบทที่ระบุไม่สามารถแมปกับ csp dll ได้ ข้อผิดพลาดจะถูกส่งกลับ เนื่องจาก MS CSP ไม่ทราบว่าควรเรียกใช้ตัวชี้ฟังก์ชันใด

ดังนั้นในกรณีนี้ แค่จัดสรรหน่วยความจำก็เพียงพอแล้ว หากแอปพลิเคชันไคลเอนต์ผ่านการจัดการบริบทที่ไม่ถูกต้อง จะไม่เข้าสู่ไลบรารี csp

ฉันคิดว่า MS CSP ใช้รายการที่มี mutex guard เพื่อจัดเก็บการแมปบริบท เนื่องจากบริบทสามารถเป็นอะไรก็ได้ตั้งแต่ตัวเลขสุ่มไปจนถึงตัวชี้ที่ถูกต้อง

person Stephan Weitlaner    schedule 05.03.2015